Django 模型的条件约束

conditional constraints for django model

提问人:whitebear 提问时间:11/16/2023 更新时间:11/16/2023 访问量:54

问:

我有这样的数据库模型

ActionType = (
    (1,"PostBack"),
    (2,"Uri"),
)

class RichMenu(BaseModel):
    key = m.CharField(max_length=64,unique=True)
    action_type = m.IntegerField(choices=ActionType,default=1)
    url = m.CharField(max_length=255,blank=True,null=True)
    name = m.CharField(max_length=255,blank=True,null=True)

现在我想做这样的约束,

  • 当为 1 时,应为 null,不应为 nullaction_typeurlname

  • 当为 2 时,应为 null,不应为 nullaction_typenameurl

是否可以对这种情况进行条件约束?

Python Django 模型

评论


答:

1赞 TanThien 11/16/2023 #1

在将方法 save() 保存到数据库之前,您可以将方法 save() 覆盖到有效字段

ActionType = (
    (1,"PostBack"),
    (2,"Uri"),
)

class RichMenu(BaseModel):
    key = m.CharField(max_length=64,unique=True)
    action_type = m.IntegerField(choices=ActionType,default=1)
    url = m.CharField(max_length=255,blank=True,null=True)
    name = m.CharField(max_length=255,blank=True,null=True)

    def save(self, *args, **kwargs):
        if self.action_type == 1:
            if self.url is not None and self.name is None:
                raise Exception("INVALID URL AND NAME")
        elif self.action_type == 2:
            if self.url is None and self.name is not None:
                raise Exception("INVALID URL AND NAME")
        super(RichMenu, self).save(*args, **kwargs)

评论

0赞 blhsing 11/16/2023
当使用 时,这很容易中断,它不调用该方法。QuerySet.updatesave
0赞 TanThien 11/16/2023
@blhsing感谢这个案例。所以,我认为它将规则有效移动到私有功能有效并在方法保存和更新中调用它
1赞 PTomasz 11/16/2023 #2

Django 2.2 引入了 CheckConstraint

class RichMenu(m.Model):
    key = m.CharField(max_length=64, unique=True)
    action_type = m.IntegerField(choices=ActionType, default=1)
    url = m.CharField(max_length=255, blank=True, null=True)
    name = m.CharField(max_length=255, blank=True, null=True)

    class Meta:
        constraints = [
            CheckConstraint(
                check=(
                    Q(
                        action_type=1,
                        url__isnull=True,
                        name__isnull=False,
                    )
                    | Q(
                        action_type=2,
                        url__isnull=False,
                        name__isnull=True,
                    )
                ),
                name='url_or_name_not_null_based_on_action_type_check',
            ),
        ]