Example #1
0
class AnswerSerializer(serializers.ModelSerializer):
    created = DateTimeUTCField(read_only=True)
    creator = ProfileFKSerializer(read_only=True, source='creator.get_profile')
    updated = DateTimeUTCField(read_only=True)
    updated_by = ProfileFKSerializer(read_only=True, source='updated_by.get_profile')
    num_helpful_votes = serializers.Field(source='num_helpful_votes')
    num_unhelpful_votes = serializers.Field(source='num_unhelpful_votes')

    class Meta:
        model = Answer
        fields = (
            'id',
            'question',
            'content',
            'created',
            'creator',
            'updated',
            'updated_by',
            'is_spam',
            'num_helpful_votes',
            'num_unhelpful_votes',
        )

    def validate_creator(self, attrs, source):
        user = getattr(self.context.get('request'), 'user')
        if user and not user.is_anonymous() and attrs.get('creator') is None:
            attrs['creator'] = user
        return attrs
Example #2
0
class QuestionSerializer(serializers.ModelSerializer):
    # Use slugs for product and topic instead of ids.
    product = serializers.SlugRelatedField(required=True, slug_field='slug')
    topic = TopicField(required=True)
    # Use usernames for creator and updated_by instead of ids.
    created = DateTimeUTCField(read_only=True)
    creator = ProfileFKSerializer(source='creator.get_profile', read_only=True)
    involved = serializers.SerializerMethodField('get_involved_users')
    is_solved = serializers.Field(source='is_solved')
    is_taken = serializers.Field(source='is_taken')
    metadata = QuestionMetaDataSerializer(source='metadata_set',
                                          required=False)
    num_votes = serializers.Field(source='num_votes')
    solution = serializers.PrimaryKeyRelatedField(read_only=True)
    taken_by = ProfileFKSerializer(source='taken_by.get_profile',
                                   read_only=True)
    updated = DateTimeUTCField(read_only=True)
    updated_by = ProfileFKSerializer(source='updated_by.get_profile',
                                     read_only=True)

    class Meta:
        model = Question
        fields = (
            'answers',
            'content',
            'created',
            'creator',
            'id',
            'involved',
            'is_archived',
            'is_locked',
            'is_solved',
            'is_spam',
            'is_taken',
            'last_answer',
            'locale',
            'metadata',
            'num_answers',
            'num_votes_past_week',
            'num_votes',
            'product',
            'solution',
            'taken_until',
            'taken_by',
            'title',
            'topic',
            'updated_by',
            'updated',
        )

    def get_involved_users(self, obj):
        involved = set([obj.creator.get_profile()])
        involved.update(a.creator.get_profile() for a in obj.answers.all())
        return ProfileFKSerializer(involved, many=True).data

    def validate_creator(self, attrs, source):
        user = getattr(self.context.get('request'), 'user')
        if user and not user.is_anonymous() and attrs.get(source) is None:
            attrs['creator'] = user
        return attrs
Example #3
0
class ImageDetailSerializer(ImageShortSerializer):
    created = DateTimeUTCField(read_only=True)
    updated = DateTimeUTCField(read_only=True)
    updated_by = serializers.SlugRelatedField(slug_field='username')

    class Meta(ImageShortSerializer.Meta):
        fields = ImageShortSerializer.Meta.fields + (
            'created', 'updated', 'updated_by', 'description', 'is_draft',
            'creator')
Example #4
0
class AnswerSerializer(serializers.ModelSerializer):
    content = SplitSourceField(read_source='content_parsed',
                               write_source='content')
    created = DateTimeUTCField(read_only=True)
    creator = serializers.SerializerMethodField('get_creator')
    num_helpful_votes = serializers.Field(source='num_helpful_votes')
    num_unhelpful_votes = serializers.Field(source='num_unhelpful_votes')
    updated = DateTimeUTCField(read_only=True)
    updated_by = serializers.SerializerMethodField('get_updated_by')

    class Meta:
        model = Answer
        fields = (
            'id',
            'question',
            'content',
            'created',
            'creator',
            'updated',
            'updated_by',
            'is_spam',
            'num_helpful_votes',
            'num_unhelpful_votes',
        )

    def get_creator(self, obj):
        return ProfileFKSerializer(Profile.objects.get(user=obj.creator)).data

    def get_updated_by(self, obj):
        updated_by = Profile.objects.get(
            user=obj.updated_by) if obj.updated_by else None
        return ProfileFKSerializer(updated_by).data if updated_by else None

    def validate_creator(self, attrs, source):
        user = getattr(self.context.get('request'), 'user')
        if user and not user.is_anonymous() and attrs.get('creator') is None:
            attrs['creator'] = user
        return attrs
Example #5
0
class RealtimeActionSerializer(serializers.ModelSerializer):
    action_object = GenericRelatedField(serializer_type='full')
    actor = GenericRelatedField(serializer_type='full')
    target = GenericRelatedField(serializer_type='full')
    verb = serializers.CharField()
    timestamp = DateTimeUTCField()

    class Meta:
        model = PushNotificationRegistration
        fields = (
            'action_object',
            'actor',
            'id',
            'target',
            'timestamp',
            'verb',
        )
Example #6
0
class NotificationSerializer(serializers.ModelSerializer):
    is_read = serializers.Field(source='is_read')
    timestamp = DateTimeUTCField(source='action.timestamp')
    actor = GenericRelatedField(source='action.actor')
    verb = serializers.CharField(source='action.verb')
    action_object = GenericRelatedField(source='action.action_object')
    target = GenericRelatedField(source='action.target')

    class Meta:
        model = PushNotificationRegistration
        fields = (
            'is_read',
            # 'read_at',
            'timestamp',
            'actor',
            'verb',
            'action_object',
            'target'
        )
Example #7
0
class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.WritableField(source='user.username')
    display_name = serializers.WritableField(source='name', required=False)
    date_joined = DateTimeUTCField(source='user.date_joined', read_only=True)
    avatar = serializers.SerializerMethodField('get_avatar_url')
    email = (PermissionMod(serializers.WritableField,
                           permissions=[OnlySelf])(source='user.email',
                                                   required=False))
    settings = (PermissionMod(UserSettingSerializer,
                              permissions=[OnlySelf])(many=True,
                                                      read_only=True))
    helpfulness = serializers.Field(source='answer_helpfulness')
    answer_count = serializers.SerializerMethodField('get_answer_count')
    question_count = serializers.SerializerMethodField('get_question_count')
    solution_count = serializers.SerializerMethodField('get_solution_count')
    # These are write only fields. It is very important they stays that way!
    password = serializers.WritableField(source='user.password',
                                         write_only=True)
    is_active = (PermissionMod(serializers.BooleanField,
                               permissions=[OnlySelf])(source='user.is_active',
                                                       read_only=True))

    class Meta:
        model = Profile
        fields = [
            'username',
            'display_name',
            'date_joined',
            'avatar',
            'bio',
            'website',
            'twitter',
            'facebook',
            'mozillians',
            'irc_handle',
            'timezone',
            'country',
            'city',
            'locale',
            'email',
            'settings',
            'helpfulness',
            'question_count',
            'answer_count',
            'solution_count',
            # Password and email are here so they can be involved in write
            # operations. They is marked as write-only above, so will not be
            # visible.
            'password',
            'is_active',
        ]

    def get_avatar_url(self, profile):
        return profile_avatar(profile.user)

    def get_question_count(self, profile):
        return num_questions(profile.user)

    def get_answer_count(self, profile):
        return num_answers(profile.user)

    def get_solution_count(self, profile):
        return num_solutions(profile.user)

    def restore_object(self, attrs, instance=None):
        """
        Override the default behavior to make a user if one doesn't exist.

        This user may not be saved here, but will be saved if/when the .save()
        method of the serializer is called.
        """
        instance = (super(ProfileSerializer,
                          self).restore_object(attrs, instance))
        if instance.user_id is None:
            # The Profile doesn't have a user, so create one. If an email is
            # specified, the user will be inactive until the email is
            # confirmed. Otherwise the user can be created immediately.
            if 'user.email' in attrs:
                u = RegistrationProfile.objects.create_inactive_user(
                    attrs['user.username'], attrs['user.password'],
                    attrs['user.email'])
            else:
                u = User(username=attrs['user.username'])
                u.set_password(attrs['user.password'])
            instance._nested_forward_relations['user'] = u
        return instance

    def validate_username(self, attrs, source):
        obj = self.object
        if obj is None:
            # This is a create
            if User.objects.filter(username=attrs['user.username']).exists():
                raise ValidationError('A user with that username exists')
        else:
            # This is an update
            new_username = attrs.get('user.username', obj.user.username)
            if new_username != obj.user.username:
                raise ValidationError("Can't change this field.")

        if re.match(r'^[\w.-]{4,30}$', attrs['user.username']) is None:
            raise ValidationError(
                'Usernames may only be letters, numbers, "." and "-".')

        return attrs

    def validate_display_name(self, attrs, source):
        if attrs.get('name') is None:
            attrs['name'] = attrs.get('user.username')
        return attrs

    def validate_email(self, attrs, source):
        email = attrs.get('user.email')
        if email and User.objects.filter(email=email).exists():
            raise ValidationError('A user with that email address '
                                  'already exists.')
        return attrs
Example #8
0
class QuestionSerializer(serializers.ModelSerializer):
    content = SplitSourceField(read_source='content_parsed',
                               write_source='content')
    created = DateTimeUTCField(read_only=True)
    creator = serializers.SerializerMethodField('get_creator')
    involved = serializers.SerializerMethodField('get_involved_users')
    is_solved = serializers.Field(source='is_solved')
    is_taken = serializers.Field(source='is_taken')
    metadata = QuestionMetaDataSerializer(source='metadata_set',
                                          required=False)
    num_votes = serializers.Field(source='num_votes')
    product = serializers.SlugRelatedField(required=True, slug_field='slug')
    tags = QuestionTagSerializer(source='tags', read_only=True)
    solution = serializers.PrimaryKeyRelatedField(read_only=True)
    solved_by = serializers.SerializerMethodField('get_solved_by')
    taken_by = serializers.SerializerMethodField('get_taken_by')
    topic = TopicField(required=True)
    updated = DateTimeUTCField(read_only=True)
    updated_by = serializers.SerializerMethodField('get_updated_by')

    class Meta:
        model = Question
        fields = (
            'answers',
            'content',
            'created',
            'creator',
            'id',
            'involved',
            'is_archived',
            'is_locked',
            'is_solved',
            'is_spam',
            'is_taken',
            'last_answer',
            'locale',
            'metadata',
            'tags',
            'num_answers',
            'num_votes_past_week',
            'num_votes',
            'product',
            'solution',
            'taken_until',
            'taken_by',
            'title',
            'topic',
            'updated_by',
            'updated',
        )

    def get_involved_users(self, obj):
        involved = set([Profile.objects.get(user=obj.creator)])
        involved.update(
            Profile.objects.get(user=a.creator) for a in obj.answers.all())
        return ProfileFKSerializer(involved, many=True).data

    def get_solved_by(self, obj):
        return ProfileFKSerializer(
            obj.solution.creator).data if obj.solution else None

    def get_creator(self, obj):
        return ProfileFKSerializer(Profile.objects.get(user=obj.creator)).data

    def get_taken_by(self, obj):
        taken_by = Profile.objects.get(
            user=obj.taken_by) if obj.taken_by else None
        return ProfileFKSerializer(taken_by).data if taken_by else None

    def get_updated_by(self, obj):
        updated_by = Profile.objects.get(
            user=obj.updated_by) if obj.updated_by else None
        return ProfileFKSerializer(updated_by).data if updated_by else None

    def validate_creator(self, attrs, source):
        user = getattr(self.context.get('request'), 'user')
        if user and not user.is_anonymous() and attrs.get(source) is None:
            attrs['creator'] = user
        return attrs
Example #9
0
class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.WritableField(source='user.username')
    display_name = serializers.WritableField(source='name', required=False)
    date_joined = DateTimeUTCField(source='user.date_joined', read_only=True)
    avatar = serializers.SerializerMethodField('get_avatar_url')
    email = (PermissionMod(serializers.EmailField,
                           permissions=[OnlySelf])(source='user.email',
                                                   required=True))
    settings = (PermissionMod(UserSettingSerializer,
                              permissions=[OnlySelf])(many=True,
                                                      read_only=True))
    helpfulness = serializers.Field(source='answer_helpfulness')
    answer_count = serializers.SerializerMethodField('get_answer_count')
    question_count = serializers.SerializerMethodField('get_question_count')
    solution_count = serializers.SerializerMethodField('get_solution_count')
    last_answer_date = serializers.SerializerMethodField(
        'get_last_answer_date')
    is_active = serializers.BooleanField(source='user.is_active',
                                         read_only=True)
    # These are write only fields. It is very important they stays that way!
    password = serializers.WritableField(source='user.password',
                                         write_only=True)

    class Meta:
        model = Profile
        fields = [
            'username',
            'display_name',
            'date_joined',
            'avatar',
            'bio',
            'website',
            'twitter',
            'facebook',
            'mozillians',
            'irc_handle',
            'timezone',
            'country',
            'city',
            'locale',
            'email',
            'settings',
            'helpfulness',
            'question_count',
            'answer_count',
            'solution_count',
            'last_answer_date',
            # Password and email are here so they can be involved in write
            # operations. They is marked as write-only above, so will not be
            # visible.
            'password',
            'is_active',
        ]

    def get_avatar_url(self, profile):
        request = self.context.get('request')
        size = request.REQUEST.get('avatar_size', 48) if request else 48
        return profile_avatar(profile.user, size=size)

    def get_question_count(self, profile):
        return num_questions(profile.user)

    def get_answer_count(self, profile):
        return num_answers(profile.user)

    def get_solution_count(self, profile):
        return num_solutions(profile.user)

    def get_last_answer_date(self, profile):
        last_answer = profile.user.answers.order_by('-created').first()
        return last_answer.created if last_answer else None

    def save_object(self, obj, **kwargs):
        """It is universally a bad idea to force_insert=True on this object. So don't."""
        kwargs.pop('force_insert', None)
        return super(ProfileSerializer, self).save_object(obj, **kwargs)

    def restore_object(self, attrs, instance=None):
        """
        Override the default behavior to make a user if one doesn't exist.

        This user may not be saved here, but will be saved if/when the .save()
        method of the serializer is called.
        """
        instance = (super(ProfileSerializer,
                          self).restore_object(attrs, instance))
        if instance.user_id is None:
            # This is a bit of cheat. The user shouldn't be saved yet, but
            # ``create_inactive_user`` saves it, so their isn't much of a choice.
            u = RegistrationProfile.objects.create_inactive_user(
                attrs['user.username'], attrs['user.password'],
                attrs['user.email'])
            instance.user_id = u.id
            instance.save()
        return instance

    def validate_username(self, attrs, source):
        obj = self.object
        if obj is None:
            # This is a create
            if User.objects.filter(username=attrs['user.username']).exists():
                raise ValidationError('A user with that username exists')
        else:
            # This is an update
            new_username = attrs.get('user.username', obj.user.username)
            if new_username != obj.user.username:
                raise ValidationError("Can't change this field.")

        if re.match(r'^[\w.-]{4,30}$', attrs['user.username']) is None:
            raise ValidationError(
                'Usernames may only be letters, numbers, "." and "-".')

        return attrs

    def validate_display_name(self, attrs, source):
        if attrs.get('name') is None:
            attrs['name'] = attrs.get('user.username')
        return attrs

    def validate_email(self, attrs, source):
        email = attrs.get('user.email')
        if email and User.objects.filter(email=email).exists():
            raise ValidationError('A user with that email address '
                                  'already exists.')
        return attrs