如果任何
unique_for_date
约束涉及不属于ModelForm
(例如,如果其中一个字段列在exclude
或具有editable=False
(,则Model.validate_unique()
将跳过这种特殊的约束。
如上所述,下面的模型为具有editable=False
的DateField
设置unique_for_date
。
根据以上文档的摘录,我希望在验证过程中跳过unique_for_date
约束。
然而,下面的测试通过了,显示Model.validate_unique()
确实由于unique_for_date
(使用Django 3.0(而引发了ValidationError
我错过了什么?
from django.db import models
from django.utils import timezone
from django.core.exceptions import ValidationError
from django.test import TransactionTestCase
class MyModel(models.Model):
name = models.CharField(max_length=10, unique_for_date='date')
date = models.DateField(editable=False)
class MyModelTests(TransactionTestCase):
def test_name_unique_for_date(self):
name = 'bird'
today = timezone.now().date()
MyModel.objects.create(name=name, date=today)
with self.assertRaises(ValidationError) as a:
MyModel(name=name, date=today).validate_unique()
self.assertIn('Name must be unique for Date date.', a.exception.messages)
感谢@WillemVanOnsem在上面的评论:
尽管文件上写着
。。。
Model.validate_unique()
将跳过该特定约束的验证。
实际上是BaseModelForm.validate_unique()
导致跳过约束。
除非我们明确设置exclude=['date']
,否则Model.validate_unique()
本身不会跳过约束。
如果我们验证一个ModelForm
实例,则带有editable=False
的date
字段将自动排除:该字段将从此处的表单中排除,因此,该字段将在此处从验证中排除。
修改示例以说明这一点:
NAME = 'bird'
TODAY = timezone.now().date()
class MyModel(models.Model):
name = models.CharField(max_length=10, unique_for_date='date')
date = models.DateField(editable=False)
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
class MyModelTests(TransactionTestCase):
def setUp(self):
MyModel.objects.create(name=NAME, date=TODAY)
def test_model_validate_name_unique_for_date(self):
# constraint is NOT skipped if we validate the Model instance directly
with self.assertRaises(ValidationError) as a:
MyModel(name=NAME, date=TODAY).validate_unique()
self.assertIn('Name must be unique for Date date.', a.exception.messages)
def test_modelform_validate_name_unique_for_date(self):
# constraint IS skipped if we validate a ModelForm instance
my_model_form = MyModelForm(data=dict(name=NAME, date=TODAY))
self.assertTrue(my_model_form.is_valid())