「一意」の2つのフィールドをカップルとして定義する方法


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がnullになる可能性がある場合、これをどのように処理しますか?その場合、MySQLは一意を強制しないようです。
グレッグ

26
参考までに、重複を追加しようとすると、django.db.utils.IntegrityErrorがスローされます。
クモ目2012年

8
@Greg-ANSI標準SQL:2003(および以前のバージョンも同様)によると、UNIQUE制約は重複する非NULL値を許可する必要がありますが、複数のNULL値を許可する必要があります(ドラフトwiscorp.com/sql_2003_standard.zip、フレームワーク、22ページを参照)。一意の制約で複数のnull値を許可しない場合はNULL、意味のある値として使用するなど、何か間違っている可能性があります。null許容フィールドは、「そのフィールドの値が常にあるとは限らないが、その場合は一意である必要がある」と述べています。

2
複数のunique_together制約についてはどうですか?たとえば、モードカラムを親のスコープ内で一意にする場合はどうすればよいですか?さて、このプロパティは、実際にタプル自体で、以下を参照してください。docs.djangoproject.com/en/1.4/ref/models/options/...をあなたの制約がより明示的として記述する必要がありますので:unique_together = (('journal_id', 'volume_number',),)
Tomasz Gandor 2014年

76

Django 2.2以降

unique_togetherよりもconstraints機能を使用することUniqueConstraintをお勧めします。

Djangoのドキュメントからunique_together

代わりに、constraintsオプションを指定したUniqueConstraintを使用してください。
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')
        ]

UniqueConstraintの 'name'パラメータはどのような状況で使用されますか?URLパスの名前パラメーターのように機能すると思いますか?
user7733611

1
@ user7733611制約に名前を付けると、さまざまな状況で役立ちます。たとえば、レガシーデータベースに接続している場合や、データベースで制約名をより人間が読めるようにしたい場合などです。MySQLデータベースの文字セットを移行したとき、Djangoが生成した制約名は実際には特定のターゲットに対して長すぎました。
mihow

UniqueConstraintpsycopg2.errors.DuplicateTable: relation "name_of_the_constraint" already exists
送信元
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.