如果未明确指定,则 DRF ModelSerializer 中的“具有此用户名的用户已存在”

soc*_*pet 4 django django-rest-framework

尽管我知道如何解决,但我正在尝试理解为什么会发生此错误。只是想更好地理解 DRF 和 Django。

这种格式的 JSON 来自 FE:

{
  "username": "username_here",
  "password": "password_here"
}
Run Code Online (Sandbox Code Playgroud)

我有这样的看法:

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)
Run Code Online (Sandbox Code Playgroud)

它使用这个序列化器:

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.
        '''})
Run Code Online (Sandbox Code Playgroud)

username = CharField()对我来说似乎多余。文档

该类ModelSerializer提供了一个快捷方式,可让您自动创建一个Serializer具有与模型字段对应的字段的类。

我将此解释为仅指定field = []in 就class Meta:足以反序列化 JSON。

但是,当我删除 时username = CharField(),我得到:

{
    "username": [
        "user with this username already exists."
    ]
}
Run Code Online (Sandbox Code Playgroud)

明确规范的文档说:

您可以ModelSerializer通过在类上声明字段来向类添加额外的字段或覆盖默认字段,就像对Serializer类所做的那样。

这使得它听起来是可选的,但显然必须指定它。

如果有人不介意解释的话,我在这里错过了什么?

Mah*_*del 8

您正在使用ModelSerializer与您的模型和请求是POST,难怪为什么您会得到这个。

ModelSerializer用于为 CRUD 操作提供快速标准序列化,因此当您的请求是时,POST序列化程序将假设您正在使用用户模型的请求数据创建新用户,因此将应用创建验证,并且用户名是唯一的... ,现在故事的其余部分就交给你了。

尝试使用基本的序列化器,因为您只想读取数据,它会更简单