我试图弄清楚在Django中创建对象时如何使用验证。
从我的POV看,有两种方法:
$scope
方法。validate_field
方法时捕获任何IntegrityError或ValidationError异常。两种方法似乎都有缺点。
通过使用方法1 ,除序列化程序外,其他任何.save()
模型调用都使我的模型不受“保护”。 方法2 处理了上述问题,但由于在序列化程序的.create()
方法中必须进行异常处理,因此使代码更加复杂。
有没有人遇到过类似的问题和/或找到了一种“清洁”的方式来解决这一问题?
答案 0 :(得分:2)
据我了解,您需要Django模型验证。您可以尝试这种方法(我想这正是您想要的)。
from django.core.exceptions import ValidationError
class Foo(models.Model):
name = models.CharField(max_length=255)
def clean(self):
raise ValidationError('Problem during validation')
f = Foo(name='test')
f.full_clean() # This is what you need. f.clean() will be enough, but f.full_clean() will make field level validations (run validators) and checking about uniqueness also.
f.save()
通常, Django 在创建模型期间从不进行模型级别的验证(不调用full_clean()
)。
f = Foo(**fields_dict)
f.save() # no validation performed.
如果需要,请自己叫
f = Foo(**fields_dict)
f.full_clean() # validation performed
f.save()
如果使用full_clean()
类,则会自动执行 ModelForm
方法。这是 Django 的附加钩子。
答案 1 :(得分:0)
我认为将验证下移至模型是确保最高级别可靠性的最安全方法,因为只要通过 Django 完成验证,就将应用验证您使用序列化程序,如果 Django Rest Framework 被跳过,则验证将无效”。
模型级别的验证可以是:
Field level validations :您创建进行验证的方法,并将该方法设置为字段验证器:
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
from django.db import models
class MyModel(models.Model):
even_field = models.IntegerField(validators=[validate_even])
Model level validations :您覆盖模型的clean()
方法并执行所需的验证:
import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _
class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError(_('Draft entries may not have a publication date.'))
# Set the pub_date for published items if it hasn't been set already.
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.date.today()