Python 基于另一个字段的值在Django模型上添加约束
我有一个简单的模型,有1个主键和3个字段(简化):Python 基于另一个字段的值在Django模型上添加约束,python,django,database,django-models,Python,Django,Database,Django Models,我有一个简单的模型,有1个主键和3个字段(简化): 及格分数 最高分数 最大尝试 此模型是通过继承django.db.models创建的。这是最小可复制代码: from django.db import models class QuestionSet(models.Model): passingscore = models.PositiveSmallIntegerField("passing score") maxscore = models.PositiveSmallIn
- 及格分数
- 最高分数
- 最大尝试
django.db.models
创建的。这是最小可复制代码:
from django.db import models
class QuestionSet(models.Model):
passingscore = models.PositiveSmallIntegerField("passing score")
maxscore = models.PositiveSmallIntegerField("max score")
maxattempt = models.PositiveSmallIntegerField("max attempt")
我想添加一个约束,使数据库中的passingscore
不得大于maxscore
。
我使用了跨越多个字段的约束,例如unique\u-together
,如所示。但显然这是一个不同的用例
我还简要考虑了直接编写PostgreSQL代码时添加约束:
ALTER TABLE tableB ADD CONSTRAINT score_policy_1 CHECK (maxscore >= passingscore)
但这违背了使用ORM的目的,违反了“松散耦合”的理念,使得在不同的数据库后端之间进行迁移变得困难
如果这是可能的,请告诉我用Django编写此约束的更惯用的方法 您可以在视图层或数据库层中执行此操作 如果要在DB层中执行此操作,可以覆盖模型的
save
方法,并在其中检查值:
def save(self, *args, **kwargs):
if self.passingscore > self.maxscore:
raise ValueError("passingscore can't be greater than maxscore")
super().save(*args, **kwargs)
如果要处理数据库约束,可以通过子类化创建自己的约束类,并将sql放入
constraint\u-sql
方法中。这在您的情况下应该有效
from django.db import models
class QuestionSet(models.Model):
passingscore = models.PositiveSmallIntegerField("passing score")
maxscore = models.PositiveSmallIntegerField("max score")
maxattempt = models.PositiveSmallIntegerField("max attempt")
class Meta:
constraints = [
models.CheckConstraint(
name="%(app_label)s_%(class)s_passingscore_lte_maxscore",
check=models.Q(passingscore__lte=models.F("maxscore")),
)
]
这有帮助吗@其实不是。元约束是我知道并很好地利用的东西,但是没有描述或说明将约束置于值或其他字段之下。谢谢你!这是一个很有帮助的建议(因此是向上投票的),但有些更新在将值持久化到数据库时甚至不调用
save()
。我希望在db层上强制执行约束,并考虑是否有方法覆盖meta
。如果这不是一个选项,那么我会同意你上面的建议,这是视图/模型中的逻辑,而不是db级别的强制。@只有这样,你才能通过子类化BaseConstraint
创建自己的约束类,并将sql放入constraint\u sql
方法中。看起来很有希望-我会试试这个(已经>一年了,所以我们已经离开了这个项目),当我能确认它有效时,我会回来把它标记为一个可接受的答案。非常感谢!