有没有办法在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)

我尝试将唯一= True作为字段journal_id和volume_number的属性,但它不起作用。


当前回答

是的,你可以使用Django类Meta定义多个字段为唯一的,如下所示:

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 = ('volume_number', 'journal_id') 

注意: 为了让事情顺利进行,你不应该将attribute unique=True添加到你在unique_together属性中定义的任何字段,否则它将不能作为唯一的一起工作。

其他回答

在Django 4.0中

UniqueConstraint()的新*表达式位置参数启用 在表达式和数据库上创建唯一的函数约束 功能。例如:

from django.db import models
from django.db.models import UniqueConstraint
from django.db.models.functions import Lower


class MyModel(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)

    class Meta:
        constraints = [
            UniqueConstraint(
                Lower('first_name'),
                Lower('last_name').desc(),
                name='first_last_name_unique',
            ),
        ]

Django 2.2 +

使用约束特性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')
        ]

是的,你可以使用Django类Meta定义多个字段为唯一的,如下所示:

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 = ('volume_number', 'journal_id') 

注意: 为了让事情顺利进行,你不应该将attribute unique=True添加到你在unique_together属性中定义的任何字段,否则它将不能作为唯一的一起工作。

在Django 4.1.1中

from django.db import models

class Volume(models.Model):
    field_1 = models.CharField("field 1", max_length=100,)
    field_2 = models.CharField("field 2", max_length=100,)
    field_3 = models.CharField("field 3", max_length=100,)


class Meta:
    unique_together = [['field_1', 'field_2']]

有一个简单的解决方案,称为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',)