概要
- Djangoでは複合主キー制約がないらしいということがわかりました。
- 本記事では、複合主キー制約に関して遭遇したエラーの原因と解決方法を記載します。
エラー内容
-
Customer
モデル(テーブル)でPrimary Key
を2つのフィールド(カラム)に設定。 - その状態でマイグレートを実施すると、以下のエラーが出てきました。
SystemCheckError: System check identified some issues:
ERRORS:
customer.Customer: (models.E026) The model cannot have more than one field with 'primary_key=True'.
原因
- Djangoの設計思想では複合主キー制約がないらしい。
- Djangoで直接のサポートはないので、複数のフィールドを組み合わせたユニーク制約を使用することで実現できます。
- 解決策は、以下の記事を参考にしました。
解決策
- まず、
id
フィールドとかで良いのでサロゲートキーを追加します。- サロゲートキー(代理キー)とは、データベース内での検索や参照を容易にするために使用されるもので、対象のデータとは直接関係のない特に意味を持たない主キーのこと。一意である必要があるため、データの重複や不整合を防止することができます。
- 次に、
UniqueConstraint
を定義して複合主キー制約を設定します。- 複数のフィールドを組み合わせて一意性を確保する制約です。
- モデルの
Meta
クラス内で定義します。 -
fields
引数に一意の制約に含めるフィールドをリストで指定すればOKです。 -
unique_together
属性は現在非推奨となっています。
- コードとしては以下のようになります。
models.py
from django.db import models
class Customer(models.Model):
id = models.IntegerField(db_column="id",
primary_key=True)
abc_id = models.CharField(db_column="abc_id",
max_length=6,
null=False)
xyz_cd = models.CharField(db_column="xyz_cd",
max_length=5,
null=False)
customer_key = models.CharField(db_column="customer_key",
max_length=100,
null=False)
create_date = models.CharField(db_column='create_date',
max_length=100,
default='',
null=True)
update_date = models.CharField(db_column='update_date',
max_length=100,
default='',
null=True)
class Meta:
constraints = [
# abc_idとxyz_cdでユニーク制約
models.UniqueConstraint(fields=['abc_id', 'xyz_cd'], name='unique_customer')
]
db_table = 'customer'
- これで、
abc_id
とxyz_cd
の組み合わせが一意であることを保証するユニーク制約が完成しました。