【问题标题】:Using Django's CheckConstraint with annotations使用带有注解的 Django CheckConstraint
【发布时间】:2020-06-03 03:02:28
【问题描述】:

我有一个 Django 模型,其中每个实例都需要一个从三个字段派生的唯一标识符:

class Example(Model):
    type = CharField(blank=False, null=False)           # either 'A' or 'B'
    timestamp = DateTimeField(default=timezone.now)
    number = models.IntegerField(null=True)             # a sequential number

这会生成[type][timestamp YEAR][number] 形式的标签,除非number 为空,否则该标签必须是唯一的。

我想我可以使用几个注释:

uid_expr = Case(
    When(
        number=None,
        then=Value(None),
    ),
    default=Concat(
        'type', ExtractYear('timestamp'), 'number',
        output_field=models.CharField()
    ),
    output_field=models.CharField()
)

uid_count_expr = Count('uid', distinct=True)

我覆盖了模型经理的get_queryset以默认应用注释,然后尝试使用CheckConstraint

class Example(Model):
    ...

    class Meta:
        constraints = [
            models.CheckConstraint(check=Q(uid_cnt=1), name='unique_uid')
        ]

这失败了,因为它无法在名为uid_cnt 的实例上找到一个字段,但是我认为Q 对象可以访问注释。看起来CheckConstraint 直接针对模型进行查询,而不是使用管理器返回的查询集:

class CheckConstraint(BaseConstraint):
    ...

    def _get_check_sql(self, model, schema_editor):
        query = Query(model=model)
    ...

有没有办法对注解应用约束?还是有更好的方法?

我真的很想在 db 层强制执行此操作。

谢谢。

【问题讨论】:

    标签: django django-models django-queryset django-q django-constraints


    【解决方案1】:

    这是伪代码,但请尝试:

    class Example(Model):
        ...
    
        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=['type', 'timestamp__year', 'number'], 
                    condition=Q(number__isnull=False),
                    name='unique_uid'
                )
            ]
    

    【讨论】:

    • 您能否格式化您的代码以使其在不需要水平滚动条的情况下全部可见?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2012-09-20
    • 2014-02-02
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多