วิธีการกำหนดสองฟิลด์“ ไม่ซ้ำกัน” เป็นคู่


388

มีวิธีกำหนดเขตข้อมูลสองแห่งที่ไม่เหมือนใครใน 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 = Trueเป็นแอตทริบิวต์ในฟิลด์journal_idและvolume_numberไม่ทำงาน

คำตอบ:


634

มีทางออกที่ง่ายสำหรับคุณที่เรียกว่า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 อาจเป็นโมฆะ Mysql ดูเหมือนจะไม่บังคับใช้เฉพาะในกรณีนั้น
เกร็ก

26
FYI มันจะพ่น django.db.utils.IntegrityError ถ้าคุณพยายามที่จะเพิ่มซ้ำ
araneae

8
@Greg - ตามมาตรฐาน ANSI SQL: 2003 (และก่อนหน้านี้เช่นกัน) UNIQUEข้อ จำกัด ควรไม่อนุญาตให้ทำซ้ำNULLค่าที่ไม่ซ้ำกันแต่อนุญาตให้มีหลายNULLค่า (ดูแบบร่างwiscorp.com/sql_2003_standard.zip , Framework, หน้า 22) หากคุณต้องการให้ข้อ จำกัด ที่เป็นเอกลักษณ์ไม่อนุญาตให้มีค่า Null หลายค่าคุณอาจทำสิ่งผิดปกติเช่นใช้NULLเป็นค่าที่มีความหมายเต็ม โปรดจำไว้ว่าเขตข้อมูล nullable กล่าวว่า "เราไม่ได้มีค่าสำหรับเขตข้อมูลนั้นเสมอ แต่เมื่อเราทำจะต้องไม่ซ้ำกัน"

2
มีunique_togetherข้อ จำกัดหลายประการอะไรบ้าง ตัวอย่างเช่น - เมื่อฉันต้องการให้คอลัมน์โหมดไม่ซ้ำกันในขอบเขตของผู้ปกครองหรือไม่ ดีคุณสมบัตินี้เป็นจริง tuple ตัวเองดู: docs.djangoproject.com/en/1.4/ref/models/options/...ดังนั้นข้อ จำกัด unique_together = (('journal_id', 'volume_number',),)ของคุณควรจะเขียนมากขึ้นอย่างชัดเจนว่า:
Tomasz Gandor

76

Django 2.2+

การใช้constraintsคุณสมบัติUniqueConstraintเป็นที่ต้องการมากกว่าunique_together

จากเอกสาร Django สำหรับunique_together:

ใช้ UniqueConstraint พร้อมตัวเลือกข้อ จำกัด แทน
UniqueConstraint มีฟังก์ชั่นการใช้งานที่เหนือกว่า
ที่ไม่ซ้ำกันอาจเลิกใช้ในอนาคต

ตัวอย่างเช่น:

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

พารามิเตอร์ 'name' ของ UniqueConstraint จะใช้ในสถานการณ์ใด ฉันคิดว่ามันทำงานเหมือนพารามิเตอร์ชื่อของเส้นทาง URL หรือไม่
user7733611

1
@ user7733611 การตั้งชื่อข้อ จำกัด มีประโยชน์ในหลาย ๆ สถานการณ์ ตัวอย่างเช่นหากคุณกำลังเชื่อมต่อกับฐานข้อมูลดั้งเดิมหรือหากคุณต้องการให้ชื่อข้อ จำกัด นั้นสามารถอ่านได้ง่ายขึ้นในฐานข้อมูล มีอยู่ครั้งหนึ่งที่ฉันย้ายชุดอักขระของฐานข้อมูล MySQL และชื่อข้อ จำกัด ที่สร้างขึ้นของ Django นั้นยาวเกินไปสำหรับเป้าหมายเฉพาะของเรา
mihow

ไม่แน่ใจ 100% ว่ามาจากไหน UniqueConstraintแต่ฉันแปลกpsycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already existsเมื่อเปลี่ยนมาใช้ Postgres
zar3bski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.