我有一个这样的模型

class ProductCode( models.Model):
    class Meta:
        unique_together=[('code','customer'), ] 
    customer = models.ForeignKey( 'customers.Customer', models.CASCADE, null=True, blank=True, )
    code = models.CharField( max_length = 20)
    product = models.ForeignKey( Product, models.CASCADE, )
    ...

问题是,如果为customer is None(DB NULL),则不会强制执行约束.它允许我多次使用(code=‘foo’,Customer=None)存储行/对象.我找到了this SO post个,这表明这个问题对于postgres用户来说是无法修复的.

有没有办法在(相对)较新的Meta constraints中强制执行这一限制?我发现the documentation有点难理解.

或者,我必须实现一个占位符客户来附加"默认"产品代码吗?

或者,另一种方法是在文本表示法前面加上customercode,然后将其设置为unique=True,并在必要时使用__startswith=__contains查找.

推荐答案

这是预期的行为:在数据库中,NULL是非常特殊的,因为NULL不等于NULL.

您可以添加第二个唯一约束,该约束在另一个字段为NULL时使用,因此:

from django.db.models import Q


class ProductCode(models.Model):
    customer = models.ForeignKey(
        'customers.Customer',
        models.CASCADE,
        null=True,
        blank=True,
    )
    code = models.CharField(max_length=20)
    product = models.ForeignKey(
        Product,
        models.CASCADE,
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=('code', 'customer'), name='code_customer_unique1'
            ),
            models.UniqueConstraint(
                fields=('code',),
                condition=Q(customer=None),
                name='code_customer_unique2',
            ),
        ]

Note:正如documentation on unique_together [Django-doc]所说,unique_together约束很可能会被弃用.文档建议使用Django的constraint framework中的UniqueConstraint [Django-doc].

Django相关问答推荐

为什么当对字段使用自定义序列化器时,Django Rest框架中Inbox字段会消失?

Django中的登录重定向

覆盖保存以创建范围的多个对象()

当前路径 **/POST 与其中任何一个都不匹配

如何组织 Django REST Framework url

当从 fastapi 发送请求时,Django 无法对 Postgres 执行查询

在 Serverless + Lambda + API Gateway HTTP API 上运行的 Django 应用程序正在重写链接以使用默认前缀

Django ORM 查询优化问题

Playframework 和 Django

如果上下文中缺少变量,如何使 Django 模板引发错误

Django REST 异常

如何在Django中获取一个组的所有用户?

可以在 Django 抽象模型中使用多重继承吗?

超过 1 个外键

在 Django 1.8 或更高版本中填充时出现Models aren't loaded yet"错误

有日期时间±无穷大吗?

在 Django 中使用 LiveServerTestCase 时使用代码登录

Django:在还原(迁移)后try 访问数据库时权限被拒绝

XlsxWriter 对象另存为 http 响应以在 Django 中创建下载

防止 django 管理员转义 html