So definieren Sie zwei Felder "eindeutig" als Paar

388

Gibt es eine Möglichkeit, einige Felder in Django als einzigartig zu definieren?

Ich habe eine Tabelle mit Bänden (von Zeitschriften) und möchte nicht mehr als eine Bandnummer für dieselbe Zeitschrift.

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)

Ich habe versucht zu setzen unique = Trueals Attribut in den Feldern journal_idund , volume_numberaber es funktioniert nicht.

Giovanni Di Milia
quelle

Antworten:

634

Für Sie gibt es eine einfache Lösung namens unique_together, die genau das tut, was Sie wollen.

Zum Beispiel:

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

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

Und in Ihrem Fall:

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',)
Jens
quelle
2
Ich würde sagen, Sie erhalten eine "ValidationError" -Ausnahme. Schauen Sie sich die Django-Dokumente an: Model.validate_unique
Jens
2
Wie würden Sie damit umgehen, wenn volume_number null sein könnte? MySQL scheint in diesem Fall nicht eindeutig zu sein.
Greg
26
Zu Ihrer Information, es wird ein django.db.utils.IntegrityError ausgelöst, wenn Sie versuchen, ein Duplikat hinzuzufügen.
Araneae
8
@Greg - Gemäß dem ANSI-Standard SQL: 2003 (und auch den vorherigen) sollte eine UNIQUEEinschränkung doppelte Nichtwerte nicht NULLzulassen, jedoch mehrere NULLWerte zulassen (siehe Entwurf wiscorp.com/sql_2003_standard.zip , Framework, S. 22). Wenn Sie möchten, dass Ihre eindeutige Einschränkung mehrere Nullwerte nicht zulässt, machen Sie wahrscheinlich etwas falsch, z. B. die Verwendung NULLals aussagekräftigen Wert. Denken Sie daran, dass im nullbaren Feld "Wir haben nicht immer einen Wert für dieses Feld, aber wenn wir dies tun, muss es eindeutig sein."
2
Was ist mit mehreren unique_together Einschränkungen? Zum Beispiel - wenn ich möchte, dass Modusspalten im Bereich des übergeordneten Elements eindeutig sind? Nun, diese Eigenschaft ist eigentlich ein Tupel selbst, siehe: docs.djangoproject.com/de/1.4/ref/models/options/… Ihre Einschränkung sollte also expliziter geschrieben werden als : unique_together = (('journal_id', 'volume_number',),).
Tomasz Gandor
76

Django 2.2+

Die Verwendung der constraintsFunktionen UniqueConstraintwird gegenüber unique_together bevorzugt .

Aus der Django-Dokumentation für unique_together:

Verwenden Sie stattdessen UniqueConstraint mit der Option Constraints.
UniqueConstraint bietet mehr Funktionen als unique_together.
unique_together ist möglicherweise in Zukunft veraltet.

Zum Beispiel:

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')
        ]
daaawx
quelle
In welcher Situation würde der Parameter 'name' der UniqueConstraint verwendet? Ich nehme an, es funktioniert wie der Name-Parameter eines URL-Pfads?
user7733611
1
@ user7733611 Das Benennen der Einschränkung kann in einer Reihe von Situationen hilfreich sein. Zum Beispiel, wenn Sie eine Verbindung zu einer Legacy-Datenbank herstellen oder wenn Sie nur möchten, dass die Einschränkungsnamen in der Datenbank besser lesbar sind. Einmal habe ich den Zeichensatz einer MySQL-Datenbank migriert und die von Django generierten Einschränkungsnamen waren tatsächlich zu lang für unser bestimmtes Ziel.
mihow
Nicht 100% sicher, dass es kommt, UniqueConstraintaber ich werde komisch, psycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already existswenn ich zu Postgres
wechsle