如何测试Django模型字段约束,及不符合约束数据可创建问题排查
问题解答
不符合模型约束的对象可以正常创建属于正常现象
Django的设计逻辑就是默认不在save()/create()执行时主动触发模型字段校验,你遇到的情况完全符合Django的默认运行规则,两个异常创建场景的具体原因如下:
- 传入整数
123可以创建:CharField会自动对非字符串类型的输入做隐式类型转换,123会被转成字符串"123"存入,不会触发类型报错。 - 长度超出
max_length限制可以创建:max_length参数默认仅作用于Django表单、Admin后台的输入校验环节,模型层默认不会对该参数做校验,只要数据库支持对应长度的内容存储(部分数据库如MySQL非严格模式下会自动截断超出长度的内容)就可以创建成功。 - 补充:
unique=True是例外,该约束会同步到数据库层面,如果你重复创建相同name的对象,数据库会抛出IntegrityError阻止创建,不需要主动触发校验也会生效。
正确测试字段约束的方法
Django的模型字段校验逻辑统一封装在实例的full_clean()方法中,测试时主动调用该方法即可验证约束是否生效,同时也可以搭配数据库层面的异常测试做双重验证。
测试示例代码
from django.core.exceptions import ValidationError, IntegrityError class TestAnimalModel(TestCase): def setUp(self): self.valid_animal = Animal.objects.create(name='TestAnimal') # 测试名称长度约束 def test_name_length_limit(self): over_length_name = 'TestAnimalWithTooManyCharacters' animal = Animal(name=over_length_name) # 调用full_clean触发校验,预期抛出ValidationError with self.assertRaises(ValidationError): animal.full_clean() # 测试名称唯一性约束 def test_name_unique_constraint(self): duplicate_animal = Animal(name='TestAnimal') # 模型层校验 with self.assertRaises(ValidationError): duplicate_animal.full_clean() # 数据库层面校验 with self.assertRaises(IntegrityError): duplicate_animal.save()
可选:配置模型自动触发校验
如果你希望每次调用save()/create()时自动执行校验,不需要手动调用full_clean(),可以重写模型的save方法:
class Animal(models.Model): name = models.CharField(unique=True, max_length=30, blank=False, null=False) def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs) class Meta: managed = True db_table = 'animal' ordering = ['name']
内容的提问来源于stack exchange,提问作者crowlek
相关产品推荐
相关产品推荐

