Python 这是验证 Django 模型字段的方法吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12945339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is this the way to validate Django model fields?
提问by Ray
As I understand it, when one creates a Django application, data is validated by the form before it's inserted into a model instance which is then written to the database. But if I want to create an additional layer of protection at the data model layer, is what I've done below the current "best practice?" I'm trying to ensure that a reviewer's name cannot be omitted nor be left blank. Should I be putting any custom validation in the 'clean' method as I've done here and then have 'save' call 'full_clean" which calls 'clean'? If not, what's the preferred method? Thanks.
据我了解,当一个人创建一个 Django 应用程序时,数据在插入到模型实例之前由表单验证,然后将其写入数据库。但是如果我想在数据模型层创建一个额外的保护层,我在当前的“最佳实践”之下做了什么?我试图确保审稿人的姓名不能被省略或留空。我应该像我在这里所做的那样在“clean”方法中放置任何自定义验证,然后让“save”调用“full_clean”调用“clean”吗?如果没有,首选方法是什么?谢谢。
class Reviewer(models.Model):
name = models.CharField(max_length=128, default=None)
def clean(self, *args, **kwargs):
if self.name == '':
raise ValidationError('Reviewer name cannot be blank')
super(Reviewer, self).clean(*args, **kwargs)
def full_clean(self, *args, **kwargs):
return self.clean(*args, **kwargs)
def save(self, *args, **kwargs):
self.full_clean()
super(Reviewer, self).save(*args, **kwargs)
采纳答案by Alasdair
Firstly, you shouldn't override full_cleanas you have done. From the django docs on full_clean:
首先,你不应该full_clean像你所做的那样覆盖。来自full_clean 上的Django 文档:
Model.full_clean(exclude=None)
This method callsModel.clean_fields(),Model.clean(), andModel.validate_unique(), in that order and raises aValidationErrorthat has amessage_dictattribute containing errors from all three stages.
Model.full_clean(exclude=None)
此方法按该顺序调用Model.clean_fields()、Model.clean()和Model.validate_unique(),并引发ValidationError具有message_dict包含所有三个阶段的错误的属性的 。
So the full_cleanmethod already calls clean, but by overriding it, you've prevented it calling the other two methods.
因此该full_clean方法已经调用了clean,但是通过覆盖它,您阻止了它调用其他两个方法。
Secondly, calling full_cleanin the savemethod is a trade off. Note that full_cleanis already called when model forms are validated, e.g. in the Django admin. So if you call full_cleanin the savemethod, then the method will run twice.
其次,调用full_clean的save方法是一个权衡。请注意,full_clean在验证模型表单时已经调用了它,例如在 Django 管理员中。因此,如果您调用full_clean该save方法,则该方法将运行两次。
It's not usually expected for the save method to raise a validation error, somebody might call saveand not catch the resulting error. However, I like that you call full_cleanrather than doing the check in the save method itself - this approach allows model forms to catch the problem first.
通常不希望 save 方法引发验证错误,有人可能会调用但save不会捕获由此产生的错误。但是,我喜欢您调用full_clean而不是在 save 方法本身中进行检查 - 这种方法允许模型表单首先捕获问题。
Finally, your cleanmethod would work, but you can actually handle your example case in the model field itself. Define your CharFieldas
最后,您的clean方法将起作用,但您实际上可以在模型字段本身中处理您的示例案例。定义你CharField为
name = models.CharField(max_length=128)
The blankoption will default to False. If the field is blank, a ValidationErrorwill be raised when you run full_clean. Putting default=Nonein your CharFielddoesn't do any harm, but it is a bit confusing when you don't actually allow Noneas a value.
该blank选项将默认为 False。如果该字段为空,ValidationError则运行时将引发a full_clean。把default=None你CharField没有做任何伤害,但它是一个有点混乱,当你不实际允许None的值。
回答by Ray
After thinking about Alasdair's answer and doing addtional reading, my sense now is that Django's models weren't designed so as to be validated on a model-only basis as I'm attempting to do. Such validation can be done, but at a cost, and it entails using validation methods in ways they weren't intended for.
在考虑了 Alasdair 的回答并进行了额外的阅读之后,我现在的感觉是 Django 的模型并没有像我试图做的那样设计为仅在模型的基础上进行验证。这样的验证是可以完成的,但需要付出一定的代价,而且它需要以非预期的方式使用验证方法。
Instead, I now believe that any constraints other than those that can be entered directly into the model field declarations (e.g. "unique=True") are supposed to be performed as a part of Form or ModelForm validation. If one wants to guard against entering invalid data into a project's database via any other means (e.g. via the ORM while working within the Python interpreter), then the validation should take place within the database itself. Thus, validation could be implemented on three levels: 1) First, implement all constraints and triggers via DDL in the database; 2) Implement any constraints available to your model fields (e.g. "unique=True"); and 3) Implement all other constraints and validations that mirror your database-level constraints and triggers within your Forms and ModelForms. With this approach, any form validation errors can be re-displayed to the user. And if the programmer is interacting directly with the database via the ORM, he/she would see the database exceptions directly.
相反,我现在认为,除了可以直接输入模型字段声明(例如“unique=True”)的约束之外的任何约束都应该作为 Form 或 ModelForm 验证的一部分执行。如果想防止通过任何其他方式(例如在 Python 解释器中工作时通过 ORM)将无效数据输入到项目的数据库中,那么验证应该在数据库本身内进行。因此,验证可以在三个层次上实现: 1) 首先,通过数据库中的 DDL 实现所有约束和触发器;2) 实现对您的模型字段可用的任何约束(例如“unique=True”);和 3) 实现所有其他约束和验证,这些约束和验证反映了您的 Forms 和 ModelForms 中的数据库级约束和触发器。通过这种方法,任何表单验证错误都可以重新显示给用户。如果程序员通过 ORM 直接与数据库交互,他/她将直接看到数据库异常。
Thoughts anyone?
有人想吗?
回答by Kevin Parker
Capturing the pre-save signals on on my models ensured clean will be called automatically.
在我的模型上捕获预保存信号确保 clean 将被自动调用。
from django.db.models.signals import pre_save
def validate_model(sender, **kwargs):
if 'raw' in kwargs and not kwargs['raw']:
kwargs['instance'].full_clean()
pre_save.connect(validate_model, dispatch_uid='validate_models')

