Python Django Rest框架编号类型仍然通过模型验证

Python Django Rest框架编号类型仍然通过模型验证,python,django,validation,django-rest-framework,Python,Django,Validation,Django Rest Framework,您好,我目前正在尝试为我的更新API编写验证。我在序列化程序中使用了类似的模型字段,因为我只希望在自定义用户模型中更新这些字段: class UpdateUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ( 'email', 'uid', 'nickname', 'eth_address', 'eth_private_key', 'evt_ad

您好,我目前正在尝试为我的更新API编写验证。我在序列化程序中使用了类似的模型字段,因为我只希望在自定义用户模型中更新这些字段:

class UpdateUserSerializer(serializers.ModelSerializer):
   class Meta:
      model = User
      fields = (
        'email', 'uid', 'nickname', 'eth_address', 'eth_private_key', 'evt_address', 'evt_private_key'
        )
Class User(AbstractUser):

    uid = models.CharField(
        "uid", max_length=255, null=True, blank=True)
    phone_number = models.CharField(
        "Phone number", max_length=255, null=True, blank=True)
    nickname = models.CharField(
        "Nickname", max_length=255, null=True, blank=True)
    status = models.PositiveSmallIntegerField("Status", default=0)
    eth_address = models.CharField(
        "Eth address", max_length=255, null=True, blank=True)
    eth_private_key = models.CharField(
        "Eth private key", max_length=255, null=True, blank=True)
    evt_address = models.CharField(
        "Evt address", max_length=255, null=True, blank=True)
    evt_private_key = models.CharField(
        "Evt private key", max_length=255, null=True, blank=True)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    # deleted

    class Meta:
        db_table = "users"

    pass
我的用户模型:

class UpdateUserSerializer(serializers.ModelSerializer):
   class Meta:
      model = User
      fields = (
        'email', 'uid', 'nickname', 'eth_address', 'eth_private_key', 'evt_address', 'evt_private_key'
        )
Class User(AbstractUser):

    uid = models.CharField(
        "uid", max_length=255, null=True, blank=True)
    phone_number = models.CharField(
        "Phone number", max_length=255, null=True, blank=True)
    nickname = models.CharField(
        "Nickname", max_length=255, null=True, blank=True)
    status = models.PositiveSmallIntegerField("Status", default=0)
    eth_address = models.CharField(
        "Eth address", max_length=255, null=True, blank=True)
    eth_private_key = models.CharField(
        "Eth private key", max_length=255, null=True, blank=True)
    evt_address = models.CharField(
        "Evt address", max_length=255, null=True, blank=True)
    evt_private_key = models.CharField(
        "Evt private key", max_length=255, null=True, blank=True)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    # deleted

    class Meta:
        db_table = "users"

    pass
这是我的DRF更新模型视图:

class update_profile(RetrieveUpdateAPIView):
    permission_classes = ()
    authentication_classes = (FirebaseAuthentication,)

    def update(self, request):
        user_data = request.data
        user = User.objects.get(uid=request.user.uid)
        serializer = UpdateUserSerializer(user, data=user_data, partial=True)

        if user_data == {}:
            raise serializers.ValidationError({'code': 400, 'data': 'Invalid JSON object'})

        for key_name in user_data:
            if key_name not in ['email', 'uid', 'nickname', 'eth_address', 'eth_private_key', 'evt_address', 'evt_private_key']:
                raise serializers.ValidationError({'code': 400, 'data': 'Invalid input ' + key_name})

        if serializer.is_valid():
            updated_user = serializer.save()
            return JsonResponse({'code': 200,'data': updated_user.uid}, status=200)
        else:
            return JsonResponse({'code': 400,'errors':serializer.errors}, status=400)
我的意见如下:

{
    "email": "test@gmail.com",
    "uid": "dqwdqwd3123123",
    "nickname":"Alan",
    "eth_address": "dwdw",
    "eth_private_key": "fwef",
    "evt_address": "dwqdqwf",
    "evt_private_key": "dwqdqqd"
}
我想在输入错误的情况下进行测试,因此我输入了错误的电子邮件,如
ErrorEmail.com
,并正确验证:

{
    "code": 400,
    "errors": {
        "email": [
            "Enter a valid email address."
        ]
    }
}

但是,当我尝试对其他类型(如
“昵称”:4123414)进行错误输入时,
即使在我设置
昵称=models.CharField(“昵称”,max_length=255,null=True,blank=True)的模型中,它仍然通过验证。
我不知道为什么number的输入值通过了验证而没有引起错误。

首先,我认为您在这里所做的大部分工作,比如检查正确的字段,都是由序列化程序本身完成的。您只需使用
is\u valid(raise=True)
,django将负责返回正确的HTTP响应(如果您使用的是默认的django错误处理程序-阅读更多)

因此,您的视图应该是这样的:

类更新\u配置文件(RetrieveUpdateAppiview):
权限\类=()
身份验证\u类=(FirebaseAuthentication,)
def更新(自我,请求):
用户_data=request.data
user=user.objects.get(uid=request.user.uid)
serializer=UpdateUserSerializer(用户,数据=user\u数据,部分=True)
如果serializer.is_有效(raise_exception=True):
更新的\u user=serializer.save()
返回JsonResponse({'code':200,'data':updated_user.uid},status=200)

然而,我也认为尼克的例子实际上是正确的。数字可以转换为字符串,这就是序列化程序所做的->它将
4123414
更改为
'4123414'
。仔细想想,这是一个完全正确的尼克。您应该尝试其他示例,比如为
状态提供一个负数

,那么是否有任何方法可以检查它在输入json中是否实际上是一个字符串?由于前端有时会调用带有数字值的api,并且他们希望它返回错误一个确定的方法是编写自定义字段验证器,请阅读此处的更多内容:因此,如果不是
is_instance(value,str)
,您必须做出一些会引发验证错误的事情。应该很简单。我不知道有什么更好的方法可以做到这一点,但听起来这可能是一个流行的问题,所以在引入自定义方法之前,我会做一些谷歌搜索。下面是一个类似的例子:我决定在视图端编写验证,因为序列化器中的所有内容都转换为字符串,但感谢您的解释