İki alanı “benzersiz” olarak çift olarak tanımlama


388

Django'da birkaç alanı benzersiz olarak tanımlamanın bir yolu var mı?

Bir ciltler tablosum var (dergilerden) ve aynı dergi için birden fazla cilt numarası istemiyorum.

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)

Ben koymak için çalıştı unique = Truealanlarda niteliği olarak journal_idve volume_numberancak çalışmıyor.

Yanıtlar:


634

Sizin için unique_together adlı tam olarak ne istediğinizi yapan basit bir çözüm var .

Örneğin:

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

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

Ve sizin durumunuzda:

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
Bir "ValidationError" istisnası alacağınızı söyleyebilirim. Django belgelerine bir göz atın: Model.validate_unique
Jens

2
Birim_sayısı boş olabilseydi bunu nasıl söylerdiniz? Mysql bu durumda benzersiz bir zorlama gibi görünmüyor.
Greg

26
FYI, bir kopya eklemeye çalışırsanız bir django.db.utils.IntegrityError atar.
araneae

8
@Greg - ANSI standart SQL: 2003'e (ve öncekilere de) göre, bir UNIQUEkısıtlama yinelenen NULLdeğerlere izin vermemeli, ancak birden çok NULLdeğere izin vermelidir (bkz. Taslak wiscorp.com/sql_2003_standard.zip , Framework, s.22 ). Benzersiz kısıtlamanızın birden fazla boş değere izin vermemesini istiyorsanız, muhtemelen NULLanlamlı bir değer olarak kullanmak gibi yanlış bir şey yapıyorsunuzdur . Unutmayın, boş değer alanı "Bu alan için her zaman bir değere sahip değiliz, ancak bunu yaptığımızda benzersiz olmalıdır."

2
Birden fazla unique_togetherkısıtlamaya ne dersiniz ? Örneğin - mod sütunlarının üst öğe kapsamında benzersiz olmasını istediğimde? Eh, bu özellik aslında bir tanımlama grubu kendisidir, bkz: docs.djangoproject.com/en/1.4/ref/models/options/... sizin kısıt daha açık olarak yazılır olmalıdır Yani: unique_together = (('journal_id', 'volume_number',),).
Tomasz Gandor

76

Django 2.2+

Kullanılması constraintsözelliklere UniqueConstraintgöre tercih edilir unique_together .

Aşağıdakiler için Django belgelerinden unique_together:

Bunun yerine kısıtlamalar seçeneğiyle UniqueConstraint kullanın.
UniqueConstraint unique_together'dan daha fazla işlevsellik sağlar.
unique_together gelecekte kullanımdan kaldırılabilir.

Örneğin:

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')
        ]

Hangi durumda UniqueConstraint'in 'name' parametresi kullanılır? Bir URL yolunun name parametresi gibi çalışır varsayalım?
user7733611

1
@ user7733611 kısıtlamanın adlandırılması bazı durumlarda yardımcı olabilir. Örneğin, eski bir veritabanına bağlanıyorsanız veya kısıtlama adlarının veritabanında daha fazla okunabilir olmasını istiyorsanız. Bir defasında bir MySQL veritabanının karakter kümesini taşıdım ve Django'nun oluşturduğu kısıtlama adları aslında bizim hedefimiz için çok uzun.
mihow

% 100 emin değilim geliyor UniqueConstraintama psycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already existsPostgres'e geçiş yaptığımda garip oluyorum
zar3bski
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.