如何将两个“唯一”字段定义为一对


387

有没有一种方法可以将几个字段定义为Django中唯一的字段?

我有一张(期刊的)卷表,而我不希望同一期刊有一个以上的卷号。

class Volume(models.Model):
    id = models.AutoField(primary_key=True)
    journal_id = models.ForeignKey(Journals, db_column='jid', null=True, verbose_name = "Journal")
    volume_number = models.CharField('Volume Number', max_length=100)
    comments = models.TextField('Comments', max_length=4000, blank=True)

我试图将unique = Trueas属性放在字段中journal_idvolume_number但是不起作用。

Answers:


633

有一个简单的解决方案称为unique_together,它可以完全满足您的要求。

例如:

class MyModel(models.Model):
  field1 = models.CharField(max_length=50)
  field2 = models.CharField(max_length=50)

  class Meta:
    unique_together = ('field1', 'field2',)

在您的情况下:

class Volume(models.Model):
  id = models.AutoField(primary_key=True)
  journal_id = models.ForeignKey(Journals, db_column='jid', null=True, verbose_name = "Journal")
  volume_number = models.CharField('Volume Number', max_length=100)
  comments = models.TextField('Comments', max_length=4000, blank=True)

  class Meta:
    unique_together = ('journal_id', 'volume_number',)

2
我会说您会收到“ ValidationError”异常。看一下Django文档:Model.validate_unique
Jens

2
如果volume_number可以为null,您将如何处理?在这种情况下,MySQL似乎不会强制执行唯一。
格雷格

26
仅供参考,如果您尝试添加重复项,则会抛出django.db.utils.IntegrityError。
araneae 2012年

8
@Greg-根据ANSI标准SQL:2003(以及以前的标准),UNIQUE约束应禁止重复的非NULL值,但允许多个NULL值(请参阅wiscorp.com/sql_2003_standard.zip草案,框架,第22页)。如果您希望自己的唯一约束禁止多个null值,则可能是在做错事,例如NULL用作有意义的值。请记住,可为空的字段表示“我们并不总是对该字段有值,但是当我们这样做时,它必须是唯一的。”

2
多重unique_together约束呢?例如-当我想让模式列在父范围内唯一时?好吧,该属性实际上是一个元组本身,请参见:docs.djangoproject.com/en/1.4/ref/models/options / ...因此,约束应更明确地写为:unique_together = (('journal_id', 'volume_number',),)
Tomasz Gandor 2014年

76

Django 2.2以上

使用constraints功能UniqueConstraint优于unique_together

从Django文档中获得unique_together

改用UniqueConstraint和Constraints选项。
UniqueConstraint提供的功能比unique_together还要多。
将来可能不推荐使用unique_together。

例如:

class Volume(models.Model):
    id = models.AutoField(primary_key=True)
    journal_id = models.ForeignKey(Journals, db_column='jid', null=True, verbose_name="Journal")
    volume_number = models.CharField('Volume Number', max_length=100)
    comments = models.TextField('Comments', max_length=4000, blank=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['journal_id', 'volume_number'], name='name of constraint')
        ]

在什么情况下,UniqueConstraint的'name'参数将用于?我认为它像URL路径的name参数一样工作吗?
user7733611

1
@ user7733611命名约束在许多情况下可能会有所帮助。例如,如果您要连接到旧版数据库,或者仅希望约束名称在数据库中更易于阅读。一次我迁移了MySQL数据库的字符集,而Django生成的约束名称实际上对于我们的特定目标来说太长了。
mihow

不是100%肯定它来自UniqueConstraint哪里,但是psycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already exists当我切换到Postgres时,我会感到很奇怪
zar3bski
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.