Cách xác định hai lĩnh vực, độc đáo là một cặp vợ chồng


388

Có cách nào để xác định một vài lĩnh vực là duy nhất trong Django không?

Tôi có một bảng các tập (của các tạp chí) và tôi không muốn nhiều hơn một số tập cho cùng một tạp chí.

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)

Tôi đã cố gắng đặt unique = Truelàm thuộc tính trong các trường journal_idvolume_numbernó không hoạt động.

Câu trả lời:


634

Có một giải pháp đơn giản cho bạn gọi là unique_together , thực hiện chính xác những gì bạn muốn.

Ví dụ:

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

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

Và trong trường hợp của bạn:

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
Tôi muốn nói rằng bạn sẽ nhận được một ngoại lệ "Xác thựcError". Hãy xem tài liệu của Django: Model.validate_unique
Jens

2
Làm thế nào bạn sẽ xử lý điều này nói nếu volume_number có thể là null? Mysql dường như sẽ không thực thi duy nhất trong trường hợp đó.
Greg

26
FYI nó ném một django.db.utils.IntegrityError nếu bạn cố gắng thêm một bản sao.
araneae

8
@Greg - Theo tiêu chuẩn SQL của ANSI: 2003 (và cả các phiên bản trước đó), một UNIQUEràng buộc sẽ không cho phép các NULLgiá trị không trùng lặp , nhưng cho phép nhiều NULLgiá trị (xem dự thảo wiscorp.com/sql_2003_stiteria.zip , Framework, p. 22). Nếu bạn muốn ràng buộc duy nhất của mình không cho phép nhiều giá trị null, có lẽ bạn đang làm gì đó sai, như sử dụng NULLnhư một giá trị đầy ý nghĩa. Hãy nhớ rằng, trường không thể nói rằng "Chúng tôi không phải lúc nào cũng có giá trị cho trường đó nhưng khi chúng tôi làm thì nó phải là duy nhất."

2
Điều gì về nhiều unique_togetherràng buộc? Ví dụ: khi tôi muốn có các cột chế độ là duy nhất trong phạm vi của cha mẹ? Chà, tài sản này thực sự là một tuple, xem: docs.djangoproject.com/en/1.4/ref/models/options/ trộm Vì vậy, ràng buộc của bạn nên được viết rõ ràng hơn là : unique_together = (('journal_id', 'volume_number',),).
Tomasz Gandor

76

Django 2.2+

Sử dụng các constraintstính năng UniqueConstraintđược ưu tiên hơn unique_together .

Từ tài liệu Django cho unique_together:

Sử dụng UniqueConstraint với tùy chọn ràng buộc thay thế.
UniqueConstraint cung cấp nhiều chức năng hơn unique_together.
unique_together có thể không được chấp nhận trong tương lai.

Ví dụ:

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

Trong trường hợp nào thì tham số 'name' của UniqueConstraint sẽ được sử dụng cho? Tôi giả sử nó hoạt động như tham số tên của đường dẫn URL?
dùng7733611

1
@ user7733611 đặt tên cho ràng buộc có thể hữu ích trong một số tình huống. Ví dụ: nếu bạn đang kết nối với cơ sở dữ liệu cũ hoặc nếu bạn chỉ muốn các tên ràng buộc dễ đọc hơn trong cơ sở dữ liệu. Một lần tôi đã di chuyển bộ ký tự của cơ sở dữ liệu MySQL và các tên ràng buộc được tạo của Django thực sự quá dài cho mục tiêu cụ thể của chúng tôi.
mihow

Không chắc chắn 100% đến từ UniqueConstraintnhưng tôi thấy lạ psycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already existskhi tôi chuyển sang Postgres
zar3bski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.