Esempio n. 1
0
class DraftCommentSerializer(serializers.ModelSerializer):
    user = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()),
        BaseUserSerializer())
    version = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=Version.unfiltered.all()),
        AddonBrowseVersionSerializer())
    canned_response = SplitField(
        serializers.PrimaryKeyRelatedField(
            queryset=CannedResponse.objects.all(), required=False),
        CannedResponseSerializer())

    class Meta:
        model = DraftComment
        fields = ('id', 'filename', 'lineno', 'comment', 'version', 'user',
                  'canned_response')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Set the instance for `AddonBrowseVersionSerializer` which requires
        # on `instance` being set correctly.
        self.fields['version'].output.instance = self.context['version']

    def validate(self, data):
        if data.get('comment') and data.get('canned_response'):
            raise serializers.ValidationError({
                'comment':
                ugettext('You can\'t submit a comment if `canned_response` is '
                         'defined.')
            })
        return data
class DraftCommentSerializer(serializers.ModelSerializer):
    user = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()),
        BaseUserSerializer())
    version = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=Version.unfiltered.all()),
        VersionSerializer())
    canned_response = SplitField(
        serializers.PrimaryKeyRelatedField(
            queryset=CannedResponse.objects.all(), required=False),
        CannedResponseSerializer())

    class Meta:
        model = DraftComment
        fields = ('id', 'filename', 'lineno', 'comment', 'version', 'user',
                  'canned_response')

    def validate(self, data):
        if data.get('comment') and data.get('canned_response'):
            raise serializers.ValidationError({
                'comment':
                ugettext('You can\'t submit a comment if `canned_response` is '
                         'defined.')
            })
        return data
Esempio n. 3
0
class DraftCommentSerializer(serializers.ModelSerializer):
    user = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()),
        BaseUserSerializer())
    version_id = serializers.PrimaryKeyRelatedField(
        queryset=Version.unfiltered.all(), source='version')
    canned_response = SplitField(
        serializers.PrimaryKeyRelatedField(
            queryset=CannedResponse.objects.all(),
            required=False),
        CannedResponseSerializer(),
        allow_null=True,
        required=False)

    class Meta:
        model = DraftComment
        fields = (
            'id', 'filename', 'lineno', 'comment',
            'version_id', 'user', 'canned_response'
        )

    def get_or_default(self, key, data, default=''):
        """Return the value of ``key`` in ``data``

        If that key is not present then return the value of ``key`` from
        ``self.instance`, otherwise return the ``default``.

        This method is a helper to simplify validation for partial updates.
        """
        retval = data.get(key)

        if retval is None and self.instance is not None:
            retval = getattr(self.instance, key)

        return retval or default

    def validate(self, data):
        canned_response = self.get_or_default('canned_response', data)
        comment = self.get_or_default('comment', data)

        if comment and canned_response:
            raise serializers.ValidationError(
                {'comment': ugettext(
                    'You can\'t submit a comment if `canned_response` is '
                    'defined.')})

        if not canned_response and not comment:
            raise serializers.ValidationError(
                {'comment': ugettext(
                    'You can\'t submit an empty comment.')})

        lineno = self.get_or_default('lineno', data)
        filename = self.get_or_default('filename', data)

        if lineno and not filename:
            raise serializers.ValidationError(
                {'comment': ugettext(
                    'You can\'t submit a line number without associating '
                    'it to a filename.')})
        return data
Esempio n. 4
0
class DraftCommentSerializer(serializers.ModelSerializer):
    user = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()),
        BaseUserSerializer())
    version = SplitField(
        serializers.PrimaryKeyRelatedField(
            queryset=Version.unfiltered.all()),
        VersionSerializer())

    class Meta:
        model = DraftComment
        fields = (
            'id', 'filename', 'lineno', 'comment',
            'version', 'user'
        )
Esempio n. 5
0
class CollectionAddonSerializer(serializers.ModelSerializer):
    addon = SplitField(
        # Only used for writes (this is input field), so there are no perf
        # concerns and we don't use any special caching.
        SlugOrPrimaryKeyRelatedField(queryset=Addon.objects.public()),
        AddonSerializer())
    notes = TranslationSerializerField(source='comments', required=False)
    collection = serializers.HiddenField(default=ThisCollectionDefault())

    class Meta:
        model = CollectionAddon
        fields = ('addon', 'notes', 'collection')
        validators = [
            UniqueTogetherValidator(
                queryset=CollectionAddon.objects.all(),
                message=_(u'This add-on already belongs to the collection'),
                fields=('addon', 'collection')),
        ]
        writeable_fields = ('notes', )
        read_only_fields = tuple(set(fields) - set(writeable_fields))

    def validate(self, data):
        if self.partial:
            # addon is read_only but SplitField messes with the initialization.
            # DRF normally ignores updates to read_only fields, so do the same.
            data.pop('addon', None)
        return super(CollectionAddonSerializer, self).validate(data)

    def to_representation(self, instance):
        request = self.context.get('request')
        out = super(CollectionAddonSerializer,
                    self).to_representation(instance)
        if request and is_gate_active(request, 'collections-downloads-shim'):
            out['downloads'] = 0
        return out
Esempio n. 6
0
class VersionSerializer(SimpleVersionSerializer):
    channel = ReverseChoiceField(choices=list(amo.CHANNEL_CHOICES_API.items()),
                                 read_only=True)
    license = SplitField(
        LicenseSlugSerializerField(required=False),
        LicenseSerializer(),
    )

    class Meta:
        model = Version
        fields = (
            'id',
            'channel',
            'compatibility',
            'edit_url',
            'file',
            'is_strict_compatibility_enabled',
            'license',
            'release_notes',
            'reviewed',
            'version',
        )
        read_only_fields = fields

    def __init__(self, instance=None, data=serializers.empty, **kwargs):
        self.addon = kwargs.pop('addon', None)
        super().__init__(instance=instance, data=data, **kwargs)
Esempio n. 7
0
class CollectionAddonSerializer(serializers.ModelSerializer):
    addon = SplitField(
        SlugOrPrimaryKeyRelatedField(
            # .no_cache() because django-cache-machine blows up otherwise.
            # Only used for writes (this is input field) so no perf concerns.
            queryset=Addon.objects.public().no_cache()),
        AddonSerializer())
    notes = TranslationSerializerField(source='comments', required=False)
    collection = serializers.HiddenField(default=ThisCollectionDefault())

    class Meta:
        model = CollectionAddon
        fields = ('addon', 'downloads', 'notes', 'collection')
        validators = [
            UniqueTogetherValidator(
                queryset=CollectionAddon.objects.all(),
                message=_(u'This add-on already belongs to the collection'),
                fields=('addon', 'collection')
            ),
        ]
        writeable_fields = (
            'notes',
        )
        read_only_fields = tuple(set(fields) - set(writeable_fields))

    def validate(self, data):
        if self.partial:
            # addon is read_only but SplitField messes with the initialization.
            # DRF normally ignores updates to read_only fields, so do the same.
            data.pop('addon')
        return super(CollectionAddonSerializer, self).validate(data)
Esempio n. 8
0
class SampleSplitFieldSerializer(serializers.Serializer):
    addon = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=Addon.objects), AddonSerializer()
    )
Esempio n. 9
0
class AddonSerializer(serializers.ModelSerializer):
    authors = AddonDeveloperSerializer(many=True,
                                       source='listed_authors',
                                       read_only=True)
    categories = CategoriesSerializerField(source='all_categories',
                                           required=False)
    contributions_url = ContributionSerializerField(source='contributions',
                                                    read_only=True)
    current_version = CurrentVersionSerializer(read_only=True)
    description = TranslationSerializerField(required=False)
    developer_comments = TranslationSerializerField(required=False)
    edit_url = serializers.SerializerMethodField()
    has_eula = serializers.SerializerMethodField()
    has_privacy_policy = serializers.SerializerMethodField()
    homepage = OutgoingURLTranslationField(required=False)
    icon_url = serializers.SerializerMethodField()
    icons = serializers.SerializerMethodField()
    is_disabled = SplitField(
        serializers.BooleanField(source='disabled_by_user', required=False),
        serializers.BooleanField(),
    )
    is_source_public = serializers.SerializerMethodField()
    is_featured = serializers.SerializerMethodField()
    name = TranslationSerializerField(required=False, max_length=50)
    previews = PreviewSerializer(many=True,
                                 source='current_previews',
                                 read_only=True)
    promoted = PromotedAddonSerializer(read_only=True)
    ratings = serializers.SerializerMethodField()
    ratings_url = serializers.SerializerMethodField()
    review_url = serializers.SerializerMethodField()
    status = ReverseChoiceField(choices=list(amo.STATUS_CHOICES_API.items()),
                                read_only=True)
    summary = TranslationSerializerField(required=False, max_length=250)
    support_email = EmailTranslationField(required=False)
    support_url = OutgoingURLTranslationField(required=False)
    tags = serializers.ListField(
        child=LazyChoiceField(
            choices=Tag.objects.values_list('tag_text', flat=True)),
        max_length=amo.MAX_TAGS,
        source='tag_list',
        required=False,
    )
    type = ReverseChoiceField(choices=list(amo.ADDON_TYPE_CHOICES_API.items()),
                              read_only=True)
    url = serializers.SerializerMethodField()
    version = DeveloperVersionSerializer(write_only=True)
    versions_url = serializers.SerializerMethodField()

    class Meta:
        model = Addon
        fields = (
            'id',
            'authors',
            'average_daily_users',
            'categories',
            'contributions_url',
            'created',
            'current_version',
            'default_locale',
            'description',
            'developer_comments',
            'edit_url',
            'guid',
            'has_eula',
            'has_privacy_policy',
            'homepage',
            'icon_url',
            'icons',
            'is_disabled',
            'is_experimental',
            'is_featured',
            'is_source_public',
            'last_updated',
            'name',
            'previews',
            'promoted',
            'ratings',
            'ratings_url',
            'requires_payment',
            'review_url',
            'slug',
            'status',
            'summary',
            'support_email',
            'support_url',
            'tags',
            'type',
            'url',
            'version',
            'versions_url',
            'weekly_downloads',
        )
        writeable_fields = (
            'categories',
            'description',
            'developer_comments',
            'homepage',
            'is_disabled',
            'is_experimental',
            'name',
            'requires_payment',
            'slug',
            'summary',
            'support_email',
            'support_url',
            'tags',
            'version',
        )
        read_only_fields = tuple(set(fields) - set(writeable_fields))

    def __init__(self, instance=None, data=serializers.empty, **kwargs):
        if instance and isinstance(data, dict):
            data.pop('version',
                     None)  # we only support version field for create
        super().__init__(instance=instance, data=data, **kwargs)

    def to_representation(self, obj):
        data = super().to_representation(obj)
        request = self.context.get('request', None)

        if request and is_gate_active(request, 'del-addons-created-field'):
            data.pop('created', None)
        if request and not is_gate_active(request, 'is-source-public-shim'):
            data.pop('is_source_public', None)
        if request and not is_gate_active(request, 'is-featured-addon-shim'):
            data.pop('is_featured', None)
        return data

    def get_has_eula(self, obj):
        return bool(getattr(obj, 'has_eula', obj.eula))

    def get_is_featured(self, obj):
        # featured is gone, but we need to keep the API backwards compatible so
        # fake it with promoted status instead.
        return bool(obj.promoted and obj.promoted.group == RECOMMENDED)

    def get_has_privacy_policy(self, obj):
        return bool(getattr(obj, 'has_privacy_policy', obj.privacy_policy))

    def get_url(self, obj):
        # Use absolutify(get_detail_url()), get_absolute_url() calls
        # get_url_path() which does an extra check on current_version that is
        # annoying in subclasses which don't want to load that version.
        return absolutify(obj.get_detail_url())

    def get_edit_url(self, obj):
        return absolutify(obj.get_dev_url())

    def get_ratings_url(self, obj):
        return absolutify(obj.ratings_url)

    def get_versions_url(self, obj):
        return absolutify(obj.versions_url)

    def get_review_url(self, obj):
        return absolutify(reverse('reviewers.review', args=[obj.pk]))

    def get_icon_url(self, obj):
        return absolutify(obj.get_icon_url(64))

    def get_icons(self, obj):
        get_icon = obj.get_icon_url

        return {
            str(size): absolutify(get_icon(size))
            for size in amo.ADDON_ICON_SIZES
        }

    def get_ratings(self, obj):
        ratings = {
            'average': obj.average_rating,
            'bayesian_average': obj.bayesian_rating,
            'count': obj.total_ratings,
            'text_count': obj.text_ratings_count,
        }
        if (request := self.context.get(
                'request', None)) and (grouped := get_grouped_ratings(
                    request, obj)):