Сериализатор DjangoRestFramework не распознает атрибут "имя пользователя", даже если он существует

Это мой serializers.py:

from rest_framework import serializers
from django.contrib.auth.models import User
from CMSApp.mixins import SetCustomErrorMessagesMixin

from django.utils.translation import gettext as _
from rest_framework.validators import UniqueValidator
from django.core.validators import RegexValidator


class UserSerializer(SetCustomErrorMessagesMixin, serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('username', 'password', 'email')
        custom_error_messages_for_validators = {
            'username': {
                UniqueValidator: _('This username is already taken. Please, try again'),
                RegexValidator: _('Invalid username')
            }
        }

    def create(self, validated_data):
        user = User.objects.create_user(
            email = validated_data['email'],
            username = validated_data['username'],
            password = validated_data['password'],
        )
        return user

и это мой mixins.py:

class SetCustomErrorMessagesMixin:
    """
    Replaces built-in validator messages with messages, defined in Meta class. 
    This mixin should be inherited before the actual Serializer class in order to call __init__ method.

    Example of Meta class:

    >>> class Meta:
    >>>     model = User
    >>>     fields = ('url', 'username', 'email', 'groups')
    >>>     custom_error_messages_for_validators = {
    >>>         'username': {
    >>>             UniqueValidator: _('This username is already taken. Please, try again'),
    >>>             RegexValidator: _('Invalid username')
    >>>         }
    >>>     }
    """
    def __init__(self, *args, **kwargs):
        # noinspection PyArgumentList
        super(SetCustomErrorMessagesMixin, self).__init__(*args, **kwargs)
        self.replace_validators_messages()

    def replace_validators_messages(self):
        for field_name, validators_lookup in self.custom_error_messages_for_validators.items():
            # noinspection PyUnresolvedReferences
            for validator in self.fields[field_name].validators:
                if type(validator) in validators_lookup:
                    validator.message = validators_lookup[type(validator)]

    @property
    def custom_error_messages_for_validators(self):
        meta = getattr(self, 'Meta', None)
        return getattr(meta, 'custom_error_messages_for_validators', {})

Когда я иду на URL /users/1, это представление, которое называется:

class user_detail(APIView):
    """
    Get, update or delete a specific user.
    """
    def get_object(self, pk):
        try:
            return User.objects.get(pk=pk)
        except User.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def get(self, request, pk):
        user = self.get_object(pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

    def put(self, request, pk):
        user = self.get_object(pk)
        serializer = UserSerializer(user, data=request.DATA)
        if serialzier.is_valid():
            serializier.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        user = self.get_object(pk)
        user.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Проблема в том, что когда я захожу на URL /users/1, Django возвращает ошибку атрибута, говоря:

AttributeError at /CMS/users/1
Got AttributeError when attempting to get a value for field `username` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Response` instance.
Original exception text was: 'Response' object has no attribute 'username'.

Я проверил свой UserSerializer и правильно указал, что

fields = ('username', 'password', 'email')

так что я не могу найти проблему. Любая идея, почему Django выдает ошибку, говоря, что "Поле сериализатора может быть названо неправильно и не соответствовать ни одному атрибуту или ключу на Response экземпляр.", хотя" имя пользователя "назван правильно?

1 ответ

Решение

Вопрос в вашем get_object метод, вы возвращаете ответ 404 вместо повышения Http404 исключение. Из-за этого Response передается в ваш сериализатор, и, очевидно, Response не имеет username поле.

Последняя часть вашей трассировки стека сказала

Исходный текст исключения был: у объекта "Response" нет атрибута "username".

Который был сигналом: есть только одно место, куда вы возвращаете Response вернуться к сериализатору.

Другие вопросы по тегам