0.Djangoは複合主キーをサポートしている?
https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys
Djangoでは複合主キーのサポートは公式にはされていない。※対応するパッケージとして以下を提供済み
「primary_key=True」が指定されているフィールドが無い場合は、自動で「id」が主キーとして追加されて動作するようなので、従来システムのDBを使っている場合、モデルを使った更新、削除が、このままでは動作しない。テーブルにidフィールドを追加するか、独自のクエリで処理する必要がある。
1.解決方法
案1:サロゲートキーを追加する
サロゲートキー(“id”)をDBに追加して、複合キーには一意制約(unique_together)を設定すれば、Djangoのモデルがそのまま使える。
(問題)DBの再構築に時間がかかり、計画停止が必要。
案2:独自クエリ―にて実装する
ORMに頼らずに、自分でクエリ―を書く実装にする。クエリの性能面等を自分でコントロールできる。
(問題)コードとテストが増える。
案3:Modelを拡張する
Djangoプロジェクトでも以前に検討されたようだが、最近はどうなっているかは、よく分からない。
https://code.djangoproject.com/ticket/373
https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys#CurrentStatus
色々、挑戦した人もいるみたいだが、結局、どれも未完か?
とりあえず、自分でモデルを拡張することで、自分の仕事で使えるように、Modelのサブクラスを作成する。とりあえずは、Djangoのすべての機能をカバーする必要はないので、あくまでも自分が必要とする単体モデルのINSERT,UPDATE,DELETEがカバーできるものならできそう。
(問題)現状のModelのコードを理解する必要がある。
案4:別のORMを作る
モデルまわりのコードを見たが、少しスパゲッティな感じもした。ざっと実装を調べていて感じたのは、Model、Manager、QuerySetでの役割がきれいに分かれてないように見受けられた。複合キー対応も含めて、簡素な自分のORM作るほうがいいような気もする。
(問題)そんな時間は無い!
案5:既にある別のORMを使う
以下は、主キーではなくて、あくまで複合外部キーのためか?
https://github.com/Arisophy/django-composite-foreignkey
(問題)適切なものが見つからない
2.結論
今のプロジェクトは、Ruby On Railsで作られたレガシーなシステムを、徐々にDjangoに移行しているところで、DBに手を加えたくない。
結論として、案2と案3で進めることにした。
INSERT,UPDATE,DELETEについては、案3でModelの拡張クラスで対応する。実際に作ってみたら、少ないコードで、いい感じで動いている。このままその拡張モデルを使いながら、プロジェクトを進めていく。
SELECTについては、そもそも、すべてORMに頼るわけにはいかないので、独自クエリ―も利用する。
拡張クラスをどう作ったかは、後日、公開します。
(2021/01/29)
以下で、パッケージを公開しました。
https://github.com/Arisophy/django-compositepk-model
(2021/06/06)
パッケージの日本語説明
(2021/03/16)
Djangoのticket373についての自分の見解は以下。