Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于另一个字段的值在Django模型上添加约束_Python_Django_Database_Django Models - Fatal编程技术网

Python 基于另一个字段的值在Django模型上添加约束

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

我有一个简单的模型,有1个主键和3个字段(简化):

  • 及格分数
  • 最高分数
  • 最大尝试
此模型是通过继承
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
方法中。看起来很有希望-我会试试这个(已经>一年了,所以我们已经离开了这个项目),当我能确认它有效时,我会回来把它标记为一个可接受的答案。非常感谢!