正确的方法来验证Django模型对象?
我仍然试图理解使用模型级别的自定义验证器来验证Django模型对象的正确方法。我知道验证通常是以表单或模型的形式完成的。但是,如果我通过Python shell中的ORM进行交互,我想确保我的数据在模型级别的完整性。这是我目前的方法:
I'm still trying to understand the correct way to validate a Django model object using a custom validator at the model level. I know that validation is usually done within a form or model form. However, I want to ensure the integrity of my data at the model level if I'm interacting with it via the ORM in the Python shell. Here's my current approach:
from django.db import models
from django.core import validators
from django.core exceptions import ValidationError
def validate_gender(value):
""" Custom validator """
if not value in ('m', 'f', 'M', 'F'):
raise ValidationError(u'%s is not a valid value for gender.' % value)
class Person(models.Model):
name = models.CharField(max_length=128)
age = models.IntegerField()
gender = models.CharField(maxlength=1, validators=[validate_gender])
def save(self, *args, **kwargs):
""" Override Person's save """
self.full_clean(exclude=None)
super(Person, self).save(*args, **kwargs)
这是我的问题:
-
我应该创建自定义验证函数,将其指定为验证器,然后覆盖Pe rson的save()函数如上所述? (顺便说一下,我知道我可以使用'选择'字段选项验证我的性别选择,但为了说明的目的,我创建了'validate_gender')。
Should I create a custom validation function, designate it as a validator, and then override the Person's save() function as I've done above? (By the way, I know I could validate my gender choices using the 'choices' field option but I created 'validate_gender' for the purpose of illustration).
如果我真的希望确保我的数据的完整性,我应该不仅仅是在模型层编写Django单元测试来进行测试,还要使用Python / Psycopg来进行相当的数据库级单元测试?我注意到,Django单元测试提高了ValidationErrors,只使用数据库的副本来测试模型对数据库模式的理解。即使我使用South进行迁移,任何数据库级别的约束都限于Django可以理解并转换成Postgres约束。如果我需要一个Django无法复制的自定义约束,如果我直接通过psql终端与数据库进行交互,我可能会将数据输入到我的数据库中,违反该约束。
If I really want to ensure the integrity of my data, should I not only write Django unit tests for testing at the model layer but also equivalent database-level unit tests using Python/Psycopg? I've noticed that Django unit tests, which raise ValidationErrors, only test the model's understanding of the database schema using a copy of the database. Even if I were to use South for migrations, any database-level constraints are limited to what Django can understand and translate into a Postgres constraint. If I need a custom constraint that Django can't replicate, I could potentially enter data into my database that violates that constraint if I'm interacting with the database directly via the psql terminal.
谢谢!
我有一个类似的误解ORM当我第一次开始使用Django。
I had a similar misunderstanding of the ORM when I first started with Django.
1)不,不要把 self.full_clean()
的保存
。或者
1) No, don't put self.full_clean()
inside of save
. Either
A)使用 ModelForm
(这将导致所有相同的验证发生 - 注意: ModelForm.is_valid()
不会显式调用 Model.full_clean
,但执行与 Model.full_clean
)。示例:
A) use a ModelForm
(which will cause all the same validation to occur - note: ModelForm.is_valid()
won't call Model.full_clean
explicitly, but will perform the exact same checks as Model.full_clean
). Example:
class PersonForm(forms.ModelForm):
class Meta:
model = Person
def add_person(request):
if request.method == 'POST':
form = PersonForm(request.POST, request.FILES)
if form.is_valid(): # Performs your validation, including ``validate_gender``
person = form.save()
return redirect('some-other-view')
else:
form = PersonForm()
# ... return response with ``form`` in the context for rendering in a template
另请注意,表单不仅仅用于在模板中呈现它们的视图 - 它们适合任何类型的使用,包括API等。运行 form.is_valid()
并收到错误,您将有 form.errors
这是一个包含表单中所有错误的字典,包括键$ '__ all __'
将包含非字段错误。
Also note, forms aren't for use only in views that render them in templates - they're great for any sort of use, including an API, etc. After running form.is_valid()
and getting errors, you'll have form.errors
which is a dictionary containing all the errors in the form, including a key called '__all__'
which will contain non-field errors.
B)只需在视图(或其他逻辑应用程序层)中使用 model_instance.full_clean()
而不是使用表单,但是表单是一个很好的抽象。
B) Simply use model_instance.full_clean()
in your view (or other logical application layer), instead of using a form, but forms are a nice abstraction for this.
2)我没有真正的解决方案,但我从来没有遇到过一个问题,即使在大型项目中(我目前与我公司合作的项目有146个表格),我也不怀疑在您的情况下也会引起关注。
2) I don't really have a solution to, but I've never run into such a problem, even in large projects (the current project I work with my company on has 146 tables) and I don't suspect it'll be a concern in your case either.