You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:06:04