Python 我应该在哪里对对象和字段进行django验证?
我正在创建一个django应用程序,它使用django Rest框架和普通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
class MyModel(models.Model):
licence_plate = CharField(max_length=20, validators=[LicencePlateValidator])
- 字段:根据正则表达式函数输入的车牌是否正确。与其他领域无关
- 对象:输入的zipcode对给定国家/地区有效。与模型中的zipcode和国家/地区相关
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()。
。有什么解决办法吗?