«пользователь с таким именем уже существует» в DRF ModelSerializer, если не указано явно - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь понять, почему эта ошибка возникает, хотя я знаю, как ее устранить. Просто пытаюсь понять DRF и Django лучше.

JSON в этом формате исходит от FE:

{
  "username": "username_here",
  "password": "password_here"
}

У меня есть это представление:

class UserSigninTokenAPIView(APIView):
    permission_classes = [AllowAny]
    serializer_class = UserSigninTokenSerializer

    def post(self, request):
        data = request.data
        serializer = UserSigninTokenSerializer(data=data)
        if serializer.is_valid(raise_exception=True):
            new_data = serializer.data
            return Response(new_data, status=HTTP_200_OK)
        return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

Который использует этот сериализатор:

class UserSigninTokenSerializer(ModelSerializer):
    username = CharField()

    class Meta:
        model = USERS
        fields = [
            'username',
            'password',
            'id'
        ]

    def validate(self, data):
        username = data['username']
        password = data['password']
        user_qs = USERS.objects.filter(username__iexact=username)
        if user_qs.exists() and user_qs.count() == 1:
            user_obj = user_qs.first()
            password_passes = user_obj.check_password(password)
            if password_passes:
                """
                A number of checks here I removed to keep this clean,
                otherwise would just use /api/token/ to get a token.
                I want user checks to pass before issuing a token,
                because having the token is what indicates they are 
                logged in successfully.
                """
                token = RefreshToken.for_user(user_obj)
                return {
                    'refresh': str(token),
                    'access': str(token.access_token)
                }
            else:
                Services.user_attempts(user_obj)
        raise ValidationError({'error': '''
            The credentials provided are invalid.
            <br>Please verify the username and password are correct.
        '''})

Мне кажется, что username = CharField() избыточен. Документация гласит:

Класс ModelSerializer предоставляет ярлык, который позволяет автоматически создавать класс Serializer с полями, соответствующими полям модели.

Я интерпретирую это как то, что просто указать field = [] в class Meta: достаточно для десериализации JSON.

Однако, когда я удаляю username = CharField(), я получаю:

{
    "username": [
        "user with this username already exists."
    ]
}

Документация для явных спецификаций гласит:

Вы можете добавить дополнительные поля к ModelSerializer или переопределить поля по умолчанию, объявив поля на класс, как и для класса Serializer.

Это делает его необязательным, но, видимо, его необходимо указывать.

Что мне здесь не хватает, если кто-то не против объяснить?

1 Ответ

1 голос
/ 05 марта 2020

Вы используете ModelSerializer с вашей моделью и запрос POST, поэтому неудивительно, что вы получаете это.

ModelSerializer используется для обеспечения быстрой стандартной сериализации для операций CRUD поэтому, когда ваш запрос POST, ваш сериализатор будет предполагать, что вы создаете нового пользователя с данными запроса для модели Users, поэтому будет применяться создание проверок, а имя пользователя уникально ..., теперь вы остальная часть истории .

Попробуйте использовать базовый c сериализатор, так как вы хотите только читать данные, это будет проще

...