Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我应该在哪里对对象和字段进行django验证?_Python_Django_Validation_Django Rest Framework - Fatal编程技术网

Python 我应该在哪里对对象和字段进行django验证?

Python 我应该在哪里对对象和字段进行django验证?,python,django,validation,django-rest-framework,Python,Django,Validation,Django Rest Framework,我正在创建一个django应用程序,它使用django Rest框架和普通django视图作为用户的入口点 我想对模型的独立字段和整个对象进行验证。例如: class MyModel(models.Model): licence_plate = CharField(max_length=20, validators=[LicencePlateValidator]) 字段:根据正则表达式函数输入的车牌是否正确。与其他领域无关 对象:输入的zipcode对给定国家/地区有效。与模型中的z

我正在创建一个django应用程序,它使用django Rest框架和普通django视图作为用户的入口点

我想对模型的独立字段和整个对象进行验证。例如:

class MyModel(models.Model):
    licence_plate = CharField(max_length=20, validators=[LicencePlateValidator])
  • 字段:根据正则表达式函数输入的车牌是否正确。与其他领域无关

  • 对象:输入的zipcode对给定国家/地区有效。与模型中的zipcode和国家/地区相关

对于DRF-API,我使用ModelSerializer,它自动调用我在模型中放置的所有验证器,例如:

class MyModel(models.Model):
    licence_plate = CharField(max_length=20, validators=[LicencePlateValidator])
由于验证器是在模型中给出的,因此API POST(因为我使用ModelSerializer)以及在django admin后端创建的对象都会得到验证

但是,当我想引入对象级验证时,我需要在序列化程序的validate()-方法中进行验证,这意味着只在API中验证对象

我还必须重写模型的save方法,以验证在Django管理页面中创建的对象


问题:这对我来说似乎有点混乱,是否有一点可以让对象级验证程序在API和管理页面上运行,就像我在字段级验证中所做的那样(我只需要将它们放在模型声明中,一切都会得到处理)

您可以创建一个单独的函数
使用_country(zipcode,country)
验证_zipcode\u,该函数将包含两个参数
zipcode
country

然后,我们将在序列化程序的
validate()
和模型的
clean()
中调用此方法

from django.core.exceptions import ValidationError

def validate_zipcode_with_country(zipcode, country):
    # check zipcode is valid for the given country 
    if not valid_zipcode:
        raise ValidationError("Zipcode is not valid for this country.") 
然后在
serializers.py
中,需要在
validate()
函数中调用此函数

class MySerializer(serializers.ModelSerializer):   

    def validate(self, attrs):
        zipcode = attrs.get('zipcode')
        country = attrs.get('country')
        validate_zipcode_with_country(zipcode, country) # call the function
        ...
class MyModel(models.Model):

    def clean(self):        
        validate_zipcode_with_country(self.zipcode, self.country) # call this function
        ...
类似地,您需要重写模型的
clean()
,并调用此函数

class MySerializer(serializers.ModelSerializer):   

    def validate(self, attrs):
        zipcode = attrs.get('zipcode')
        country = attrs.get('country')
        validate_zipcode_with_country(zipcode, country) # call the function
        ...
class MyModel(models.Model):

    def clean(self):        
        validate_zipcode_with_country(self.zipcode, self.country) # call this function
        ...

对于模型级验证,有
model.clean
方法

如果您使用的是
ModelForm
(默认情况下在
admin
中使用),则会调用它,因此这将解决django视图和管理部分的问题

另一方面,DRF不会自动调用模型的
clean
,因此您必须自己在
序列化程序中进行验证(如图所示)。您可以通过序列化程序mixin执行此操作:

class ValidateModelMixin(object)
    def validate(self, attrs):
        attrs = super().validate(attrs)
        obj = self.Meta.model(**attrs)
        obj.clean()
        return attrs

class SomeModelSerializer(ValidateModelMixin, serializers.ModelSerializer):
    #...
    class Meta:
        model = SomeModel
或者编写一个验证器:

class DelegateToModelValidator(object):

    def set_context(self, serializer):
        self.model = serializer.Meta.model

    def __call__(self, attrs):
        obj = self.model(**attrs)
        obj.clean()

class SomeModelSerializer(serializers.ModelSerializer):
    #...
    class Meta:
        model = SomeModel
        validators = (
            DelegateToModelValidator(),
        )
注意事项:

  • 一个额外的模型实例化,只需调用
    clean
  • 您仍然需要将mixin/validator添加到序列化程序中

Ah tnx,这个答案和Rahul的答案让我更清楚地认识到,在两个位置调用模型验证器(一个在序列化程序中,一个在模型中)确实是通过表单和API进行验证的唯一方法。它给了我一些如何以更干净的方式编写代码的想法。我想我会走混合路线。。。对我来说似乎更干净。这会导致
类型错误:禁止直接分配到多对多集合的前端。当与具有关系的模型一起使用时,请改用users.set()。
。有什么解决办法吗?