示例#1
0
class WebsiteSerializer(serializers.ModelSerializer):
    categories = ListField(serializers.CharField())
    description = TranslationSerializerField()
    device_types = ListField(serializers.CharField(), source='device_names')
    icons = serializers.SerializerMethodField('get_icons')
    id = serializers.IntegerField(source='pk')
    keywords = serializers.SerializerMethodField('get_keywords')
    name = TranslationSerializerField()
    promo_imgs = serializers.SerializerMethodField('get_promo_imgs')
    short_name = TranslationSerializerField()
    title = TranslationSerializerField()

    class Meta:
        model = Website
        fields = [
            'categories', 'description', 'device_types', 'icons', 'id',
            'keywords', 'mobile_url', 'name', 'promo_imgs', 'short_name',
            'title', 'url'
        ]

    def get_icons(self, obj):
        return {
            icon_size: obj.get_icon_url(icon_size)
            for icon_size in CONTENT_ICON_SIZES
        }

    def get_keywords(self, obj):
        if not hasattr(obj, 'keywords_list'):
            attach_tags([obj])
        return getattr(obj, 'keywords_list', [])

    def get_promo_imgs(self, obj):
        return dict([(promo_img_size, obj.get_promo_img_url(promo_img_size))
                     for promo_img_size in mkt.PROMO_IMG_SIZES])
示例#2
0
 def test_field_null(self):
     field = TranslationSerializerField()
     app = Webapp()
     result = field.field_to_native(app, "name")
     eq_(result, None)
     result = field.field_to_native(app, "description")
     eq_(result, None)
示例#3
0
 def test_field_to_native_request_GET(self):
     request = Request(self.factory.get('/'))
     mock_serializer = Serializer()
     mock_serializer.context = {'request': request}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_dict(field)
示例#4
0
 def test_field_to_native_request_POST(self):
     request = Request(self.factory.post("/"))
     mock_serializer = Serializer()
     mock_serializer.context = {"request": request}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, "name")
     self._test_expected_dict(field)
示例#5
0
 def test_field_to_native_request_GET(self):
     request = Request(self.factory.get('/'))
     mock_serializer = Serializer()
     mock_serializer.context = {'request': request}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_dict(field)
示例#6
0
    def test_field_to_native(self):
        class TestObject(object):
            test_field = u'Yes We Can'

        field = TranslationSerializerField()
        result = field.field_to_native(TestObject(), 'test_field')
        eq_(result, TestObject.test_field)
示例#7
0
 def test_field_null(self):
     field = TranslationSerializerField()
     app = Webapp()
     result = field.field_to_native(app, 'name')
     eq_(result, None)
     result = field.field_to_native(app, 'description')
     eq_(result, None)
示例#8
0
 def test_field_from_native_strip(self):
     data = {
         'fr': u'  Non mais Allô quoi ! ',
         'en-US': u''
     }
     field = TranslationSerializerField()
     result = field.from_native(data)
     eq_(result, {'fr': u'Non mais Allô quoi !', 'en-US': u''})
示例#9
0
 def test_field_to_native_source(self):
     self.app.mymock = Mock()
     self.app.mymock.mymocked_field = self.app.name
     field = TranslationSerializerField(source="mymock.mymocked_field")
     result = field.field_to_native(self.app, "shouldbeignored")
     expected = {
         "en-US": unicode(Translation.objects.get(id=self.app.name.id, locale="en-US")),
         "es": unicode(Translation.objects.get(id=self.app.name.id, locale="es")),
     }
     eq_(result, expected)
示例#10
0
class CollectionSerializer(serializers.ModelSerializer):
    name = TranslationSerializerField()
    description = TranslationSerializerField()
    slug = serializers.CharField(required=False)
    collection_type = serializers.IntegerField()
    apps = CollectionMembershipField(many=True,
                                     source='collectionmembership_set')
    image = HyperlinkedRelatedOrNullField(
        source='*',
        view_name='collection-image-detail',
        predicate=lambda o: o.has_image)
    carrier = SlugChoiceField(required=False,
        choices_dict=mkt.carriers.CARRIER_MAP)
    region = SlugChoiceField(required=False,
        choices_dict=mkt.regions.REGIONS_DICT)
    category = SlugModelChoiceField(required=False,
        queryset=Category.objects.filter(type=amo.ADDON_WEBAPP))

    class Meta:
        fields = ('apps', 'author', 'background_color', 'carrier', 'category',
                  'collection_type', 'default_language', 'description', 'id',
                  'image', 'is_public', 'name', 'region', 'slug',
                  'text_color',)
        model = Collection

    def full_clean(self, instance):
        instance = super(CollectionSerializer, self).full_clean(instance)
        if not instance:
            return None
        # For featured apps and operator shelf collections, we need to check if
        # one already exists for the same region/category/carrier combination.
        #
        # Sadly, this can't be expressed as a db-level unique constaint,
        # because this doesn't apply to basic collections.
        #
        # We have to do it  ourselves, and we need the rest of the validation
        # to have already taken place, and have the incoming data and original
        # data from existing instance if it's an edit, so full_clean() is the
        # best place to do it.
        unique_collections_types = (COLLECTIONS_TYPE_FEATURED,
                                    COLLECTIONS_TYPE_OPERATOR)
        qs = Collection.objects.filter(
            collection_type=instance.collection_type,
            category=instance.category,
            region=instance.region,
            carrier=instance.carrier)
        if instance.pk:
            qs = qs.exclude(pk=instance.pk)
        if (instance.collection_type in unique_collections_types and
            qs.exists()):
            self._errors['collection_uniqueness'] = _(
                u'You can not have more than one Featured Apps/Operator Shelf '
                u'collection for the same category/carrier/region combination.'
            )
        return instance
示例#11
0
 def test_field_to_native_source(self):
     self.app.mymock = Mock()
     self.app.mymock.mymocked_field = self.app.name
     field = TranslationSerializerField(source='mymock.mymocked_field')
     result = field.field_to_native(self.app, 'shouldbeignored')
     expected = {
         'en-US': unicode(Translation.objects.get(id=self.app.name.id,
                                                  locale='en-US')),
         'es': unicode(Translation.objects.get(id=self.app.name.id,
                                               locale='es')),
     }
     eq_(result, expected)
示例#12
0
class FeedCollectionSerializer(BaseFeedCollectionSerializer):
    """
    A serializer for the FeedCollection class.
    """
    type = serializers.ChoiceField(choices=constants.COLLECTION_TYPE_CHOICES)
    background_image = FeedImageField(
        source='*', view_name='api-v2:feed-collection-image-detail',
        format='png')
    color = serializers.CharField(max_length=20, required=False)
    description = TranslationSerializerField(required=False)
    name = TranslationSerializerField()
    apps = serializers.SerializerMethodField('get_apps')

    # Deprecated.
    background_color = serializers.CharField(max_length=7, required=False)

    class Meta:
        fields = ('app_count', 'apps', 'background_color', 'background_image',
                  'color', 'description', 'id', 'name', 'slug', 'type', 'url')
        model = FeedCollection
        url_basename = 'feedcollections'

    def validate_color(self, attrs, source):
        color = attrs.get(source, None)
        if (attrs.get('type') == constants.COLLECTION_PROMO and not color):
            raise serializers.ValidationError(
                '`color` is required for `promo` collections.'
            )
        if color and color not in dict(collection_colors.COLLECTION_COLORS):
            raise serializers.ValidationError(
                '`Not a valid value for `color`.'
            )
        return attrs

    def get_apps(self, obj):
        """
        Return a list of serialized apps, adding each app's `group` to the
        serialization.
        """
        ret = []
        memberships = FeedCollectionMembership.objects.filter(obj_id=obj.id)
        field = TranslationSerializerField()
        field.initialize(self, 'group')
        field.context = self.context
        for member in memberships:
            data = AppSerializer(member.app, context=self.context).data
            data['group'] = field.field_to_native(member, 'group')
            ret.append(data)
        return ret
示例#13
0
    def test_field_to_native(self):
        app = Webapp.objects.get(pk=337141)
        field = TranslationSerializerField()
        result = field.field_to_native(app, 'name')
        expected = {
            'en-US': Translation.objects.get(id=app.name.id, locale='en-US'),
            'es': Translation.objects.get(id=app.name.id, locale='es')
        }
        eq_(result, expected)

        result = field.field_to_native(app, 'description')
        expected = {
            'en-US':
            Translation.objects.get(id=app.description.id, locale='en-US'),
        }
        eq_(result, expected)
示例#14
0
 def test_field_to_native_request_GET_lang(self):
     """
     Pass a lang in the query string, expect to have a single string
     returned instead of an object.
     """
     # Note that we don't go through the middlewares etc so the actual
     # language for the process isn't changed, we don't care as
     # _expect_single_string() method simply tests with the current language,
     # whatever it is.
     request = Request(self.factory.get('/', {'lang': 'lol'}))
     eq_(request.GET['lang'], 'lol')
     mock_serializer = Serializer()
     mock_serializer.context = {'request': request}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_single_string(field)
示例#15
0
 def test_field_to_native_request_GET_lang(self):
     """
     Pass a lang in the query string, expect to have a single string
     returned instead of an object.
     """
     # Note that we don't go through the middlewares etc so the actual
     # language for the process isn't changed, we don't care as
     # _expect_single_string() method simply tests with the current language,
     # whatever it is.
     request = Request(self.factory.get('/', {'lang': 'lol'}))
     eq_(request.GET['lang'], 'lol')
     mock_serializer = Serializer()
     mock_serializer.context = {'request': request}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_single_string(field)
示例#16
0
    def test_field_to_native(self):
        app = Webapp.objects.get(pk=337141)
        field = TranslationSerializerField()
        result = field.field_to_native(app, 'name')
        expected = {
            'en-US': Translation.objects.get(id=app.name.id, locale='en-US'),
            'es': Translation.objects.get(id=app.name.id, locale='es')
        }
        eq_(result, expected)

        result = field.field_to_native(app, 'description')
        expected = {
            'en-US': Translation.objects.get(id=app.description.id, 
                                             locale='en-US'),
        }
        eq_(result, expected)
示例#17
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_attribution = TranslationSerializerField(required=False)
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'description', 'id', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'url')
        model = FeedApp
        url_basename = 'feedapp'
示例#18
0
    def test_from_native(self):
        data = u'Translatiön'
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = {'fr': u'Non mais Allô quoi !', 'en-US': u'No But Hello what!'}
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = ['Bad Data']
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, unicode(data))
示例#19
0
class FeedShelfSerializer(BaseFeedCollectionSerializer):
    """
    A serializer for the FeedBrand class, a type of collection that allows
    editors to quickly create content without involving localizers.
    """
    apps = serializers.SerializerMethodField('get_apps')
    background_image = FeedImageField(
        source='*', view_name='api-v2:feed-shelf-image-detail', format='png')
    background_image_landing = FeedLandingImageField(
        source='*',
        view_name='api-v2:feed-shelf-landing-image-detail',
        format='png')
    carrier = SlugChoiceField(choices_dict=mkt.carriers.CARRIER_MAP)
    description = TranslationSerializerField(required=False)
    is_published = serializers.BooleanField(source='is_published',
                                            required=False)
    name = TranslationSerializerField()
    region = SlugChoiceField(choices_dict=mkt.regions.REGION_LOOKUP)

    class Meta:
        fields = [
            'app_count', 'apps', 'background_image',
            'background_image_landing', 'carrier', 'description', 'id',
            'is_published', 'name', 'region', 'slug', 'url'
        ]
        model = FeedShelf
        url_basename = 'feedshelves'

    def get_apps(self, obj):
        """
        Return a list of serialized apps, adding each app's `group` to the
        serialization.
        """
        ret = []
        memberships = FeedShelfMembership.objects.filter(obj_id=obj.id)
        field = TranslationSerializerField()
        field.initialize(self, 'group')
        field.context = self.context
        for member in memberships:
            data = AppSerializer(member.app, context=self.context).data
            data['group'] = field.field_to_native(member, 'group')
            ret.append(data)
        return ret
示例#20
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """Thin wrappers around apps w/ metadata related to its feature in feed."""
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    image = CollectionImageField(source='*',
                                 view_name='feed-app-image-detail',
                                 format='png')
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_attribution = TranslationSerializerField(required=False)
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'description', 'feedapp_type',
                  'id', 'image', 'preview', 'pullquote_attribution',
                  'pullquote_rating', 'pullquote_text', 'slug', 'url')
        model = FeedApp
        url_basename = 'feedapps'
示例#21
0
class CollectionSerializer(serializers.ModelSerializer):
    name = TranslationSerializerField()
    description = TranslationSerializerField()
    slug = serializers.CharField(required=False)
    collection_type = serializers.IntegerField()
    apps = CollectionMembershipField(many=True,
                                     source='collectionmembership_set')

    class Meta:
        fields = ('apps', 'author', 'background_color', 'carrier', 'category',
                  'collection_type', 'default_language', 'description', 'id',
                  'is_public', 'name', 'region', 'slug', 'text_color',)
        model = Collection

    def full_clean(self, instance):
        instance = super(CollectionSerializer, self).full_clean(instance)
        if not instance:
            return None
        # For featured apps and operator shelf collections, we need to check if
        # one already exists for the same region/category/carrier combination.
        #
        # Sadly, this can't be expressed as a db-level unique constaint,
        # because this doesn't apply to basic collections.
        #
        # We have to do it  ourselves, and we need the rest of the validation
        # to have already taken place, and have the incoming data and original
        # data from existing instance if it's an edit, so full_clean() is the
        # best place to do it.
        unique_collections_types = (COLLECTIONS_TYPE_FEATURED,
                                    COLLECTIONS_TYPE_OPERATOR)
        if (instance.collection_type in unique_collections_types and
            Collection.objects.filter(collection_type=instance.collection_type,
                                      category=instance.category,
                                      region=instance.region,
                                      carrier=instance.carrier).exists()):
            self._errors['collection_uniqueness'] = _(
                u'You can not have more than one Featured Apps/Operator Shelf '
                u'collection for the same category/carrier/region combination.'
            )
        return instance
示例#22
0
class ExtensionSerializer(ModelSerializer):
    description = TranslationSerializerField(read_only=True)
    device_types = ListField(CharField(), source='device_names')
    icons = SerializerMethodField('get_icons')
    latest_public_version = ExtensionVersionSerializer(
        source='latest_public_version', read_only=True)
    latest_version = ExtensionVersionSerializer(source='latest_version',
                                                read_only=True)
    mini_manifest_url = CharField(source='mini_manifest_url', read_only=True)
    name = TranslationSerializerField(read_only=True)
    status = ReverseChoiceField(choices_dict=STATUS_CHOICES_API_v2,
                                read_only=True)

    # FIXME: latest_version potentially expose private data.
    # Nothing extremely major, but maybe we care. Not a fan of moving it to
    # another endpoint since that'd mean developers and reviewers would need
    # to use that other endpoint instead of the regular one, but maybe that's
    # the way to go ? That endpoint could include all versions info, too.

    def get_icons(self, obj):
        return {size: obj.get_icon_url(size) for size in (64, 128)}

    class Meta:
        model = Extension
        fields = [
            'id',
            'author',
            'description',
            'device_types',
            'disabled',
            'icons',
            'last_updated',
            'latest_version',
            'latest_public_version',
            'mini_manifest_url',
            'name',
            'slug',
            'status',
            'uuid',
        ]
示例#23
0
class FeedAppSerializer(ValidateSlugMixin, URLSerializerMixin,
                        serializers.ModelSerializer):
    """
     A serializer for the FeedApp class, which highlights a single app and some
    additional metadata (e.g. a review or a screenshot).
    """
    app = SplitField(
        relations.PrimaryKeyRelatedField(required=True,
                                         queryset=Webapp.objects),
        AppSerializer())
    background_image = FeedImageField(allow_null=True)
    description = TranslationSerializerField(required=False)
    preview = SplitField(
        relations.PrimaryKeyRelatedField(required=False,
                                         queryset=Preview.objects),
        FeedPreviewESSerializer())
    pullquote_rating = serializers.IntegerField(required=False,
                                                max_value=5,
                                                min_value=1)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'background_image', 'color',
                  'created', 'description', 'id', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'slug', 'type', 'url')
        model = FeedApp
        url_basename = 'feedapps'

    def validate(self, attrs):
        """
        Require `pullquote_text` if `pullquote_rating` or
        `pullquote_attribution` are set.
        """
        if (not attrs.get('pullquote_text')
                and (attrs.get('pullquote_rating')
                     or attrs.get('pullquote_attribution'))):
            raise ValidationError('Pullquote text required if rating or '
                                  'attribution is defined.')
        return attrs
示例#24
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """
    A serializer for the FeedApp class, which highlights a single app and some
    additional metadata (e.g. a review or a screenshot).
    """
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    background_image = CollectionImageField(
        source='*', view_name='api-v2:feed-app-image-detail', format='png')
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'created', 'description',
                  'feedapp_type', 'id', 'background_image', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'slug', 'url')
        model = FeedApp
        url_basename = 'feedapps'
示例#25
0
class FeedShelfSerializer(BaseFeedCollectionSerializer):
    """
    A serializer for the FeedBrand class, a type of collection that allows
    editors to quickly create content without involving localizers.
    """
    background_image = FeedImageField(
        source='*', view_name='api-v2:feed-shelf-image-detail', format='png')
    background_image_landing = FeedLandingImageField(
        source='*', view_name='api-v2:feed-shelf-landing-image-detail',
        format='png')
    carrier = SlugChoiceField(choices_dict=mkt.carriers.CARRIER_MAP)
    description = TranslationSerializerField(required=False)
    is_published = serializers.BooleanField(source='is_published',
                                            required=False)
    name = TranslationSerializerField()
    region = SlugChoiceField(choices_dict=mkt.regions.REGION_LOOKUP)

    class Meta:
        fields = ['app_count', 'apps', 'background_image',
                  'background_image_landing', 'carrier', 'description', 'id',
                  'is_published', 'name', 'region', 'slug', 'url']
        model = FeedShelf
        url_basename = 'feedshelves'
示例#26
0
 def get_apps(self, obj):
     """
     Return a list of serialized apps, adding each app's `group` to the
     serialization.
     """
     ret = []
     memberships = FeedShelfMembership.objects.filter(obj_id=obj.id)
     field = TranslationSerializerField()
     field.bind('group', self)
     field.context = self.context
     for member in memberships:
         data = AppSerializer(member.app, context=self.context).data
         data['group'] = field.to_representation(
             field.get_attribute(member))
         ret.append(data)
     return ret
示例#27
0
 def get_apps(self, obj):
     """
     Return a list of serialized apps, adding each app's `group` to the
     serialization.
     """
     ret = []
     memberships = FeedCollectionMembership.objects.filter(obj_id=obj.id)
     field = TranslationSerializerField()
     field.initialize(self, 'group')
     field.context = self.context
     for member in memberships:
         data = AppSerializer(member.app, context=self.context).data
         data['group'] = field.field_to_native(member, 'group')
         ret.append(data)
     return ret
示例#28
0
    def test_from_native(self):
        data = u"Translatiön"
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = {"fr": u"Non mais Allô quoi !", "en-US": u"No But Hello what!"}
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = ["Bad Data"]
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, unicode(data))
示例#29
0
 def get_apps(self, obj):
     """
     Return a list of serialized apps, adding each app's `group` to the
     serialization.
     """
     ret = []
     memberships = FeedShelfMembership.objects.filter(obj_id=obj.id)
     field = TranslationSerializerField()
     field.bind('group', self)
     field.context = self.context
     for member in memberships:
         data = AppSerializer(member.app, context=self.context).data
         data['group'] = field.to_representation(
             field.get_attribute(member))
         ret.append(data)
     return ret
示例#30
0
    def test_from_native(self):
        data = u'Translatiön'
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = {
            'fr': u'Non mais Allô quoi !',
            'en-US': u'No But Hello what!'
        }
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, data)

        data = ['Bad Data']
        field = TranslationSerializerField()
        result = field.from_native(data)
        eq_(result, unicode(data))
示例#31
0
class CollectionSerializer(serializers.ModelSerializer):
    name = TranslationSerializerField()
    description = TranslationSerializerField()
    slug = serializers.CharField(required=False)
    collection_type = serializers.IntegerField()
    apps = CollectionMembershipField(many=True, source='apps')
    image = HyperlinkedRelatedOrNullField(
        source='*',
        view_name='collection-image-detail',
        format='png',
        predicate=lambda o: o.has_image)
    carrier = SlugChoiceField(required=False, empty=None,
        choices_dict=mkt.carriers.CARRIER_MAP)
    region = SlugChoiceField(required=False, empty=None,
        choices_dict=mkt.regions.REGION_LOOKUP)
    category = SlugModelChoiceField(required=False,
        queryset=Category.objects.filter(type=amo.ADDON_WEBAPP))

    class Meta:
        fields = ('apps', 'author', 'background_color', 'can_be_hero',
                  'carrier', 'category', 'collection_type', 'default_language',
                  'description', 'id', 'image', 'is_public', 'name', 'region',
                  'slug', 'text_color',)
        model = Collection

    def to_native(self, obj):
        """
        Remove `can_be_hero` from the serialization if this is not an operator
        shelf.
        """
        native = super(CollectionSerializer, self).to_native(obj)
        if native['collection_type'] != COLLECTIONS_TYPE_OPERATOR:
            del native['can_be_hero']
        return native

    def validate(self, attrs):
        """
        Prevent operator shelves from being associated with a category.
        """
        existing = getattr(self, 'object')
        exc = 'Operator shelves may not be associated with a category.'

        if (not existing and attrs['collection_type'] ==
            COLLECTIONS_TYPE_OPERATOR and attrs.get('category')):
            raise serializers.ValidationError(exc)

        elif existing:
            collection_type = attrs.get('collection_type',
                                        existing.collection_type)
            category = attrs.get('category', existing.category)
            if collection_type == COLLECTIONS_TYPE_OPERATOR and category:
                raise serializers.ValidationError(exc)

        return attrs

    def full_clean(self, instance):
        instance = super(CollectionSerializer, self).full_clean(instance)
        if not instance:
            return None
        # For featured apps and operator shelf collections, we need to check if
        # one already exists for the same region/category/carrier combination.
        #
        # Sadly, this can't be expressed as a db-level unique constaint,
        # because this doesn't apply to basic collections.
        #
        # We have to do it  ourselves, and we need the rest of the validation
        # to have already taken place, and have the incoming data and original
        # data from existing instance if it's an edit, so full_clean() is the
        # best place to do it.
        unique_collections_types = (COLLECTIONS_TYPE_FEATURED,
                                    COLLECTIONS_TYPE_OPERATOR)
        qs = Collection.objects.filter(
            collection_type=instance.collection_type,
            category=instance.category,
            region=instance.region,
            carrier=instance.carrier)
        if instance.pk:
            qs = qs.exclude(pk=instance.pk)
        if (instance.collection_type in unique_collections_types and
            qs.exists()):
            self._errors['collection_uniqueness'] = _(
                u'You can not have more than one Featured Apps/Operator Shelf '
                u'collection for the same category/carrier/region combination.'
            )
        return instance
示例#32
0
文件: api.py 项目: lissyx/zamboni
class AppSerializer(serializers.ModelSerializer):
    app_type = serializers.ChoiceField(
        choices=amo.ADDON_WEBAPP_TYPES_LOOKUP.items(), read_only=True)
    author = serializers.CharField(source='developer_name', read_only=True)
    banner_message = TranslationSerializerField(read_only=True,
        source='geodata.banner_message')
    banner_regions = serializers.Field(source='geodata.banner_regions_slugs')
    categories = serializers.SlugRelatedField(source='categories',
        many=True, slug_field='slug', required=True,
        queryset=Category.objects.filter(type=amo.ADDON_WEBAPP))
    content_ratings = serializers.SerializerMethodField('get_content_ratings')
    created = serializers.DateField(read_only=True)
    current_version = serializers.CharField(
        source='current_version.version',
        read_only=True)
    default_locale = serializers.CharField(read_only=True)
    device_types = SemiSerializerMethodField('get_device_types')
    description = TranslationSerializerField(required=False)
    homepage = TranslationSerializerField(required=False)
    icons = serializers.SerializerMethodField('get_icons')
    id = serializers.IntegerField(source='pk', required=False)
    is_packaged = serializers.BooleanField(read_only=True)
    manifest_url = serializers.CharField(source='get_manifest_url',
                                         read_only=True)
    name = TranslationSerializerField(required=False)
    payment_account = serializers.SerializerMethodField('get_payment_account')
    payment_required = serializers.SerializerMethodField(
        'get_payment_required')
    premium_type = ReverseChoiceField(
        choices_dict=amo.ADDON_PREMIUM_API, required=False)
    previews = PreviewSerializer(many=True, required=False,
                                 source='all_previews')
    price = SemiSerializerMethodField('get_price')
    price_locale = serializers.SerializerMethodField('get_price_locale')
    privacy_policy = LargeTextField(view_name='app-privacy-policy-detail',
                                    required=False)
    public_stats = serializers.BooleanField(read_only=True)
    ratings = serializers.SerializerMethodField('get_ratings_aggregates')
    regions = RegionSerializer(read_only=True, source='get_regions')
    release_notes = TranslationSerializerField(read_only=True,
        source='current_version.releasenotes')
    resource_uri = serializers.HyperlinkedIdentityField(view_name='app-detail')
    slug = serializers.CharField(source='app_slug', required=False)
    status = serializers.IntegerField(read_only=True)
    support_email = TranslationSerializerField(required=False)

    support_url = TranslationSerializerField(required=False)
    supported_locales = serializers.SerializerMethodField(
        'get_supported_locales')
    tags = serializers.SerializerMethodField('get_tags')
    upsell = serializers.SerializerMethodField('get_upsell')
    upsold = serializers.HyperlinkedRelatedField(
        view_name='app-detail', source='upsold.free',
        required=False, queryset=Webapp.objects.all())
    user = serializers.SerializerMethodField('get_user_info')
    versions = serializers.SerializerMethodField('get_versions')
    weekly_downloads = serializers.SerializerMethodField(
        'get_weekly_downloads')

    class Meta:
        model = Webapp
        fields = [
            'app_type', 'author', 'banner_message', 'banner_regions',
            'categories', 'content_ratings', 'created', 'current_version',
            'default_locale', 'description', 'device_types', 'homepage',
            'icons', 'id', 'is_packaged', 'manifest_url', 'name',
            'payment_account', 'payment_required', 'premium_type', 'previews',
            'price', 'price_locale', 'privacy_policy', 'public_stats',
            'release_notes', 'ratings', 'regions', 'resource_uri', 'slug',
            'status', 'support_email', 'support_url', 'supported_locales',
            'tags', 'upsell', 'upsold', 'user', 'versions', 'weekly_downloads']

    def _get_region_id(self):
        request = self.context.get('request')
        REGION = getattr(request, 'REGION', None)
        return REGION.id if REGION else None

    def _get_region_slug(self):
        request = self.context.get('request')
        REGION = getattr(request, 'REGION', None)
        return REGION.slug if REGION else None

    def get_content_ratings(self, app):
        body = mkt.regions.REGION_TO_RATINGS_BODY().get(
            self._get_region_slug(), 'generic')
        return {
            'body': body,
            'rating': app.get_content_ratings_by_body().get(body, None),
            'descriptors': app.get_descriptors_dehydrated().get(body, []),
            'interactives': app.get_interactives_dehydrated(),
        }

    def get_icons(self, app):
        return dict([(icon_size, app.get_icon_url(icon_size))
                     for icon_size in (16, 48, 64, 128)])

    def get_payment_account(self, app):

        # Avoid a query for payment_account if the app is not premium.
        if not app.is_premium():
            return None

        try:
            # This is a soon to be deprecated API property that only
            # returns the Bango account for historic compatibility.
            app_acct = app.payment_account(PROVIDER_BANGO)
            return reverse('payment-account-detail',
                           args=[app_acct.payment_account.pk])
        except app.PayAccountDoesNotExist:
            return None

    def get_payment_required(self, app):
        if app.has_premium():
            tier = app.get_tier()
            return bool(tier and tier.price)
        return False

    def get_price(self, app):
        if app.has_premium():
            region = self._get_region_id()
            if region in app.get_price_region_ids():
                return app.get_price(region=region)
        return None

    def get_price_locale(self, app):
        if app.has_premium():
            region = self._get_region_id()
            if region in app.get_price_region_ids():
                return app.get_price_locale(region=region)
        return None

    def get_ratings_aggregates(self, app):
        return {'average': app.average_rating,
                'count': app.total_reviews}

    def get_supported_locales(self, app):
        locs = getattr(app.current_version, 'supported_locales', '')
        if locs:
            return locs.split(',') if isinstance(locs, basestring) else locs
        else:
            return []

    def get_tags(self, app):
        return [t.tag_text for t in app.tags.all()]

    def get_upsell(self, app):
        upsell = False
        if app.upsell:
            upsell = app.upsell.premium
        # Only return the upsell app if it's public and we are not in an
        # excluded region.
        if (upsell and upsell.is_public() and self._get_region_id()
                not in upsell.get_excluded_region_ids()):
            return {
                'id': upsell.id,
                'app_slug': upsell.app_slug,
                'icon_url': upsell.get_icon_url(128),
                'name': unicode(upsell.name),
                'resource_uri': reverse('app-detail', kwargs={'pk': upsell.pk})
            }
        else:
            return False

    def get_user_info(self, app):
        user = getattr(self.context.get('request'), 'amo_user', None)
        if user:
            return {
                'developed': app.addonuser_set.filter(
                    user=user, role=amo.AUTHOR_ROLE_OWNER).exists(),
                'installed': app.has_installed(user),
                'purchased': app.pk in user.purchase_ids(),
            }

    def get_versions(self, app):
        # Disable transforms, we only need two fields: version and pk.
        # Unfortunately, cache-machine gets in the way so we can't use .only()
        # (.no_transforms() is ignored, defeating the purpose), and we can't use
        # .values() / .values_list() because those aren't cached :(
        return dict((v.version, reverse('version-detail', kwargs={'pk': v.pk}))
                    for v in app.versions.all().no_transforms())

    def get_weekly_downloads(self, app):
        if app.public_stats:
            return app.weekly_downloads

    def validate_categories(self, attrs, source):
        if not attrs.get('categories'):
            raise serializers.ValidationError('This field is required.')
        set_categories = set(attrs[source])
        total = len(set_categories)
        max_cat = amo.MAX_CATEGORIES

        if total > max_cat:
            # L10n: {0} is the number of categories.
            raise serializers.ValidationError(ngettext(
                'You can have only {0} category.',
                'You can have only {0} categories.',
                max_cat).format(max_cat))

        return attrs

    def get_device_types(self, app):
        with no_translation():
            return [n.api_name for n in app.device_types]

    def save_device_types(self, obj, new_types):
        new_types = [amo.DEVICE_LOOKUP[d].id for d in new_types]
        old_types = [x.id for x in obj.device_types]

        added_devices = set(new_types) - set(old_types)
        removed_devices = set(old_types) - set(new_types)

        for d in added_devices:
            obj.addondevicetype_set.create(device_type=d)
        for d in removed_devices:
            obj.addondevicetype_set.filter(device_type=d).delete()

        # Send app to re-review queue if public and new devices are added.
        if added_devices and obj.status in amo.WEBAPPS_APPROVED_STATUSES:
            mark_for_rereview(obj, added_devices, removed_devices)

    def save_categories(self, obj, categories):
        before = set(obj.categories.values_list('id', flat=True))
        # Add new categories.
        to_add = set(c.id for c in categories) - before
        for c in to_add:
            AddonCategory.objects.create(addon=obj, category_id=c)

        # Remove old categories.
        to_remove = before - set(categories)
        for c in to_remove:
            obj.addoncategory_set.filter(category=c).delete()

    def save_upsold(self, obj, upsold):
        current_upsell = obj.upsold
        if upsold and upsold != obj.upsold.free:
            if not current_upsell:
                log.debug('[1@%s] Creating app upsell' % obj.pk)
                current_upsell = AddonUpsell(premium=obj)
            current_upsell.free = upsold
            current_upsell.save()

        elif current_upsell:
            # We're deleting the upsell.
            log.debug('[1@%s] Deleting the app upsell' % obj.pk)
            current_upsell.delete()

    def save_price(self, obj, price):
        premium = obj.premium
        if not premium:
            premium = AddonPremium()
            premium.addon = obj
        premium.price = Price.objects.active().get(price=price)
        premium.save()

    def validate_device_types(self, attrs, source):
        if attrs.get('device_types') is None:
            raise serializers.ValidationError('This field is required.')
        for v in attrs['device_types']:
            if v not in amo.DEVICE_LOOKUP.keys():
                raise serializers.ValidationError(
                    str(v) + ' is not one of the available choices.')
        return attrs

    def validate_price(self, attrs, source):
        if attrs.get('premium_type', None) not in (amo.ADDON_FREE,
                                                   amo.ADDON_FREE_INAPP):
            valid_prices = Price.objects.exclude(
                price='0.00').values_list('price', flat=True)
            price = attrs.get('price')
            if not (price and Decimal(price) in valid_prices):
                raise serializers.ValidationError(
                    'Premium app specified without a valid price. Price can be'
                    ' one of %s.' % (', '.join('"%s"' % str(p)
                                               for p in valid_prices),))
        return attrs

    def restore_object(self, attrs, instance=None):
        # restore_object creates or updates a model instance, during
        # input validation.
        extras = []
        # Upsell bits are handled here because we need to remove it
        # from the attrs dict before deserializing.
        upsold = attrs.pop('upsold.free', None)
        if upsold is not None:
            extras.append((self.save_upsold, upsold))
        price = attrs.pop('price', None)
        if price is not None:
            extras.append((self.save_price, price))
        device_types = attrs['device_types']
        if device_types:
            extras.append((self.save_device_types, device_types))
            del attrs['device_types']
        instance = super(AppSerializer, self).restore_object(
            attrs, instance=instance)
        for f, v in extras:
            f(instance, v)
        return instance

    def save_object(self, obj, **kwargs):
        # this only gets called if validation succeeds.
        m2m = getattr(obj, '_m2m_data', {})
        cats = m2m.pop('categories', None)
        super(AppSerializer, self).save_object(obj, **kwargs)
        # Categories are handled here because we can't look up
        # existing ones until the initial save is done.
        self.save_categories(obj, cats)
示例#33
0
class CannedResponseSerializer(serializers.ModelSerializer):
    name = TranslationSerializerField(required=True)
    response = TranslationSerializerField(required=True)

    class Meta:
        model = CannedResponse
示例#34
0
class AppSerializer(serializers.ModelSerializer):

    app_type = serializers.ChoiceField(
        choices=amo.ADDON_WEBAPP_TYPES_LOOKUP.items(), read_only=True)
    author = serializers.CharField(source='developer_name', read_only=True)
    categories = serializers.SlugRelatedField(
        many=True,
        slug_field='slug',
        required=True,
        queryset=Category.objects.filter(type=amo.ADDON_WEBAPP))
    content_ratings = serializers.SerializerMethodField('get_content_ratings')
    created = serializers.DateField(read_only=True)
    current_version = serializers.CharField(source='current_version.version',
                                            read_only=True)
    default_locale = serializers.CharField(read_only=True)
    device_types = SemiSerializerMethodField('get_device_types')
    description = TranslationSerializerField(required=False)
    homepage = TranslationSerializerField(required=False)
    icons = serializers.SerializerMethodField('get_icons')
    id = serializers.IntegerField(source='pk', required=False)
    is_packaged = serializers.BooleanField(read_only=True)
    manifest_url = serializers.CharField(source='get_manifest_url',
                                         read_only=True)
    name = TranslationSerializerField(required=False)
    payment_account = serializers.HyperlinkedRelatedField(
        view_name='payment-account-detail',
        source='app_payment_account',
        required=False)
    payment_required = serializers.SerializerMethodField(
        'get_payment_required')
    premium_type = ReverseChoiceField(choices_dict=amo.ADDON_PREMIUM_API,
                                      required=False)
    previews = PreviewSerializer(many=True, required=False)
    price = SemiSerializerMethodField('get_price')
    price_locale = serializers.SerializerMethodField('get_price_locale')
    privacy_policy = LargeTextField(view_name='app-privacy-policy-detail',
                                    required=False)
    public_stats = serializers.BooleanField(read_only=True)
    ratings = serializers.SerializerMethodField('get_ratings_aggregates')
    regions = RegionSerializer(read_only=True, source='get_regions')
    resource_uri = serializers.HyperlinkedIdentityField(view_name='app-detail')
    slug = serializers.CharField(source='app_slug', required=False)
    status = serializers.IntegerField(read_only=True)
    summary = TranslationSerializerField(required=False)
    support_email = TranslationSerializerField(required=False)

    support_url = TranslationSerializerField(required=False)
    supported_locales = serializers.SerializerMethodField(
        'get_supported_locales')
    tags = serializers.SerializerMethodField('get_tags')
    upsell = serializers.SerializerMethodField('get_upsell')
    upsold = serializers.HyperlinkedRelatedField(view_name='app-detail',
                                                 source='upsold.free',
                                                 required=False,
                                                 queryset=Webapp.objects.all())
    user = serializers.SerializerMethodField('get_user_info')
    versions = serializers.SerializerMethodField('get_versions')
    weekly_downloads = serializers.SerializerMethodField(
        'get_weekly_downloads')

    class Meta:
        model = Webapp
        exclude = [
            '_latest_version', 'ts_slowness', '_backup_version',
            'last_updated', 'nomination_message', '_current_version',
            'make_public', 'charity', 'modified'
        ]

    def get_content_ratings(self, app):
        return {
            'ratings': app.get_content_ratings_by_region() or None,
            'descriptors': app.get_descriptors() or None,
            'interactive_elements': app.get_interactives() or None,
        }

    def get_icons(self, app):
        return dict([(icon_size, app.get_icon_url(icon_size))
                     for icon_size in (16, 48, 64, 128)])

    def get_payment_required(self, app):
        if app.premium:
            tier = app.get_tier()
            return bool(tier and tier.price)
        return False

    def get_price(self, app):
        region = self.context.get('region')
        if (region in app.get_price_region_ids()
                or payments_enabled(self.context['request'])):
            return app.get_price(region=region)

    def get_price_locale(self, app):
        region = self.context.get('region')
        if (region in app.get_price_region_ids()
                or payments_enabled(self.context['request'])):
            return app.get_price_locale(region=region)

    def get_ratings_aggregates(self, app):
        return {'average': app.average_rating, 'count': app.total_reviews}

    def get_supported_locales(self, app):
        locs = getattr(app.current_version, 'supported_locales', '')
        if locs:
            return locs.split(',')
        else:
            return []

    def get_tags(self, app):
        return [t.tag_text for t in app.tags.all()]

    def get_upsell(self, app):
        if (app.upsell and self.context.get('region')
                in app.upsell.premium.get_price_region_ids()):
            upsell = app.upsell.premium
            return {
                'id': upsell.id,
                'app_slug': upsell.app_slug,
                'icon_url': upsell.get_icon_url(128),
                'name': unicode(upsell.name),
                'resource_uri': reverse('app-detail', kwargs={'pk': upsell.pk})
            }
        else:
            return False

    def get_user_info(self, app):
        user = self.context.get('profile')
        if user:
            return {
                'developed':
                app.addonuser_set.filter(user=user,
                                         role=amo.AUTHOR_ROLE_OWNER).exists(),
                'installed':
                app.has_installed(user),
                'purchased':
                app.pk in user.purchase_ids(),
            }

    def get_versions(self, app):
        return dict(
            (v.version, reverse_version(v)) for v in app.versions.all())

    def get_weekly_downloads(self, app):
        if app.public_stats:
            return app.weekly_downloads

    def validate_categories(self, attrs, source):
        if not attrs.get('categories'):
            raise serializers.ValidationError('This field is required.')
        set_categories = set(attrs[source])
        total = len(set_categories)
        max_cat = amo.MAX_CATEGORIES

        if total > max_cat:
            # L10n: {0} is the number of categories.
            raise serializers.ValidationError(
                ngettext('You can have only {0} category.',
                         'You can have only {0} categories.',
                         max_cat).format(max_cat))
        return attrs

    def get_device_types(self, app):
        with no_translation():
            return [n.api_name for n in app.device_types]

    def save_device_types(self, obj, new_types):
        new_types = [amo.DEVICE_LOOKUP[d].id for d in new_types]
        old_types = [x.id for x in obj.device_types]

        added_devices = set(new_types) - set(old_types)
        removed_devices = set(old_types) - set(new_types)

        for d in added_devices:
            obj.addondevicetype_set.create(device_type=d)
        for d in removed_devices:
            obj.addondevicetype_set.filter(device_type=d).delete()

        # Send app to re-review queue if public and new devices are added.
        if added_devices and obj.status in amo.WEBAPPS_APPROVED_STATUSES:
            mark_for_rereview(obj, added_devices, removed_devices)

    def save_categories(self, obj, categories):
        before = set(obj.categories.values_list('id', flat=True))
        # Add new categories.
        to_add = set(c.id for c in categories) - before
        for c in to_add:
            AddonCategory.objects.create(addon=obj, category_id=c)

        # Remove old categories.
        to_remove = before - set(categories)
        for c in to_remove:
            obj.addoncategory_set.filter(category=c).delete()

        # Disallow games in Brazil without a rating.
        games = Webapp.category('games')
        if not games:
            return

        for region in ALL_REGIONS_WITH_CONTENT_RATINGS:
            if (self.product.listed_in(region)
                    and not self.product.content_ratings_in(region)):

                if games.id in to_add:
                    aer, created = AddonExcludedRegion.objects.get_or_create(
                        addon=self.product, region=region.id)
                    if created:
                        log.info(u'[Webapp:%s] Game excluded from new region '
                                 u'(%s).' % (self.product, region.slug))

                elif games.id in to_remove:
                    self.product.addonexcludedregion.filter(
                        region=region.id).delete()
                    log.info(u'[Webapp:%s] Game no longer excluded from region'
                             u' (%s).' % (self.product, region.slug))

    def save_upsold(self, obj, upsold):
        current_upsell = obj.upsold
        if upsold and upsold != obj.upsold.free:
            if not current_upsell:
                log.debug('[1@%s] Creating app upsell' % obj.pk)
                current_upsell = AddonUpsell(premium=obj)
            current_upsell.free = upsold
            current_upsell.save()

        elif current_upsell:
            # We're deleting the upsell.
            log.debug('[1@%s] Deleting the app upsell' % obj.pk)
            current_upsell.delete()

    def save_price(self, obj, price):
        premium = obj.premium
        if not premium:
            premium = AddonPremium()
            premium.addon = obj
        premium.price = Price.objects.active().get(price=price)
        premium.save()

    def validate_device_types(self, attrs, source):
        if attrs.get('device_types') is None:
            raise serializers.ValidationError('This field is required.')
        for v in attrs['device_types']:
            if v not in amo.DEVICE_LOOKUP.keys():
                raise serializers.ValidationError(
                    str(v) + ' is not one of the available choices.')
        return attrs

    def validate_price(self, attrs, source):
        if attrs.get('premium_type',
                     None) not in (amo.ADDON_FREE, amo.ADDON_FREE_INAPP):
            valid_prices = Price.objects.exclude(price='0.00').values_list(
                'price', flat=True)
            price = attrs.get('price')
            if not (price and Decimal(price) in valid_prices):
                raise serializers.ValidationError(
                    'Premium app specified without a valid price. Price can be'
                    ' one of %s.' % (', '.join('"%s"' % str(p)
                                               for p in valid_prices), ))
        return attrs

    def restore_object(self, attrs, instance=None):
        # restore_object creates or updates a model instance, during
        # input validation.
        extras = []
        # Upsell bits are handled here because we need to remove it
        # from the attrs dict before deserializing.
        upsold = attrs.pop('upsold.free', None)
        if upsold is not None:
            extras.append((self.save_upsold, upsold))
        price = attrs.pop('price', None)
        if price is not None:
            extras.append((self.save_price, price))
        device_types = attrs['device_types']
        if device_types:
            extras.append((self.save_device_types, device_types))
            del attrs['device_types']
        if attrs.get('app_payment_account') is None:
            attrs.pop('app_payment_account')
        instance = super(AppSerializer, self).restore_object(attrs,
                                                             instance=instance)
        for f, v in extras:
            f(instance, v)
        return instance

    def save_object(self, obj, **kwargs):
        # this only gets called if validation succeeds.
        m2m = getattr(obj, '_m2m_data', {})
        cats = m2m.pop('categories', None)
        super(AppSerializer, self).save_object(obj, **kwargs)
        # Categories are handled here because we can't look up
        # existing ones until the initial save is done.
        self.save_categories(obj, cats)
示例#35
0
class BaseAppSerializer(serializers.ModelSerializer):
    # REST Framework 3.x doesn't allow meta.fields to omit fields declared in
    # the class body, but it does allow omitting ones in superclasses. All the
    # serializers are subsets of the full field collection, hence this
    # superclass.
    app_type = serializers.ChoiceField(
        choices=mkt.ADDON_WEBAPP_TYPES_LOOKUP.items(), read_only=True)
    author = serializers.CharField(source='developer_name', read_only=True)
    categories = serializers.ListField(child=serializers.ChoiceField(
        choices=CATEGORY_CHOICES, read_only=False),
                                       read_only=False,
                                       required=True)
    content_ratings = serializers.SerializerMethodField()
    created = serializers.DateTimeField(read_only=True, format=None)
    current_version = serializers.CharField(source='current_version.version',
                                            read_only=True)
    default_locale = serializers.CharField(read_only=True)
    device_types = SemiSerializerMethodField()
    description = TranslationSerializerField(required=False)
    homepage = TranslationSerializerField(required=False)
    feature_compatibility = serializers.SerializerMethodField()
    file_size = serializers.IntegerField(read_only=True)
    icons = serializers.SerializerMethodField()
    id = serializers.IntegerField(source='pk', required=False)
    is_disabled = serializers.BooleanField(read_only=True)
    is_homescreen = serializers.SerializerMethodField()
    is_offline = serializers.BooleanField(read_only=True)
    is_packaged = serializers.BooleanField(read_only=True)
    last_updated = serializers.DateTimeField(read_only=True, format=None)
    manifest_url = serializers.CharField(source='get_manifest_url',
                                         read_only=True)
    modified = serializers.DateTimeField(read_only=True, format=None)
    name = TranslationSerializerField(required=False)
    package_path = serializers.CharField(source='get_package_path',
                                         read_only=True)
    payment_account = serializers.SerializerMethodField()
    payment_required = serializers.SerializerMethodField()
    premium_type = ReverseChoiceField(choices_dict=mkt.ADDON_PREMIUM_API,
                                      required=False)
    previews = PreviewSerializer(many=True,
                                 required=False,
                                 source='all_previews')
    price = SemiSerializerMethodField(source='*', required=False)
    price_locale = serializers.SerializerMethodField()
    privacy_policy = LargeTextField(view_name='app-privacy-policy-detail',
                                    queryset=Webapp.objects,
                                    required=False)
    promo_imgs = serializers.SerializerMethodField()
    public_stats = serializers.BooleanField(read_only=True)
    ratings = serializers.SerializerMethodField('get_ratings_aggregates')
    regions = RegionSerializer(read_only=True, source='get_regions', many=True)
    release_notes = TranslationSerializerField(
        read_only=True, source='current_version.releasenotes')
    resource_uri = serializers.HyperlinkedIdentityField(view_name='app-detail')
    slug = serializers.CharField(source='app_slug', required=False)
    status = serializers.IntegerField(read_only=True)
    support_email = TranslationSerializerField(required=False)
    support_url = TranslationSerializerField(required=False)
    supported_locales = serializers.SerializerMethodField()
    tags = serializers.SerializerMethodField()
    upsell = serializers.SerializerMethodField()
    upsold = serializers.HyperlinkedRelatedField(view_name='app-detail',
                                                 source='upsold.free',
                                                 required=False,
                                                 queryset=Webapp.objects.all())
    user = serializers.SerializerMethodField('get_user_info')
    versions = serializers.SerializerMethodField()
示例#36
0
 def test_field_to_native_empty_context(self):
     mock_serializer = Serializer()
     mock_serializer.context = {}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_dict(field)
示例#37
0
 def test_field_from_native_strip(self):
     data = {"fr": u"  Non mais Allô quoi ! ", "en-US": u""}
     field = TranslationSerializerField()
     result = field.from_native(data)
     eq_(result, {"fr": u"Non mais Allô quoi !", "en-US": u""})
示例#38
0
 def test_field_to_native_empty_context(self):
     mock_serializer = Serializer()
     mock_serializer.context = {}
     field = TranslationSerializerField()
     field.initialize(mock_serializer, 'name')
     self._test_expected_dict(field)
示例#39
0
 def test_field_to_native(self):
     field = TranslationSerializerField()
     self._test_expected_dict(field)
示例#40
0
 def test_field_from_native_strip(self):
     data = {'fr': u'  Non mais Allô quoi ! ', 'en-US': u''}
     field = TranslationSerializerField()
     result = field.from_native(data)
     eq_(result, {'fr': u'Non mais Allô quoi !', 'en-US': u''})