syncdbの時のForeignKeyがつく条件ってなに?
Django で syncdb 叩いた時に、同じように models.ForeignKey を使ってるのに結果が違う。簡単なアプリを作ってテストしてみた。テスト環境はこんな感じ。
models.py はこんな感じ。
from django.db import models
class Oya(models.Model):
body = models.TextField()
class Ko(models.Model):
parent = models.ForeignKey(Oya)
body = models.TextField()
これで sql を叩くとこう出てくる。
BEGIN;
CREATE TABLE `hige_ko` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`parent_id` integer NOT NULL,
`body` longtext NOT NULL
);
CREATE TABLE `hige_oya` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`body` longtext NOT NULL
);
ALTER TABLE `hige_ko` ADD CONSTRAINT parent_id_refs_id_4d095607 FOREIGN KEY (`parent_id`) REFERENCES `hige_oya` (`id`);
COMMIT;
hige_ko (Ko) が先に作られて hige_oya (Oya) が作られる。で、ちゃんと ALTER TABLE で外部キーを付け足してる事が分かる。これが期待してる通りの形。ココで models.py を書き換えてみる。
class Oya(models.Model):
body = models.TextField()
# KoからKodomoへ変更。
class Kodomo(models.Model):
parent = models.ForeignKey(Oya)
body = models.TextField()
もう一回 sql を叩くとこう出る。
BEGIN;
CREATE TABLE `hige_oya` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`body` longtext NOT NULL
);
CREATE TABLE `hige_kodomo` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`parent_id` integer NOT NULL REFERENCES `hige_oya` (`id`),
`body` longtext NOT NULL
);
COMMIT;
今度は hige_oya (Oya) が先に作られて次に hige_kodomo (Kodomo) が作られる。 ALTER TABLE 文が消えて、代わりにカラム定義部分に REFERENCES の一文が付いた。
この2つをそれぞれ syncdb 叩いて実際にテーブルを作ってみる。以下、それぞれの SHOW CREATE TABLE の実行結果。
mysql> SHOW CREATE TABLE `hige_ko`\G
*************************** 1. row ***************************
Table: hige_ko
Create Table: CREATE TABLE `hige_ko` (
`id` int(11) NOT NULL auto_increment,
`parent_id` int(11) NOT NULL,
`body` longtext NOT NULL,
PRIMARY KEY (`id`),
KEY `hige_ko_parent_id` (`parent_id`),
CONSTRAINT `parent_id_refs_id_4d095607` FOREIGN KEY (`parent_id`) REFERENCES `hige_oya` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
次に後者だとこうなった。
mysql> SHOW CREATE TABLE `hige_kodomo`\G
*************************** 1. row ***************************
Table: hige_kodomo
Create Table: CREATE TABLE `hige_kodomo` (
`id` int(11) NOT NULL auto_increment,
`parent_id` int(11) NOT NULL,
`body` longtext NOT NULL,
PRIMARY KEY (`id`),
KEY `hige_kodomo_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
やっぱり後者には外部キー制約が付けられてない。ほとんど同じコードで実行してるのにこの違いはなんだ?これだと最初のクラス名を決める段階で生成されるSQLを意識せざるを得ない。それに、「生成されるかも知れない。されないかも知れない。」ってのが痛い。
かなり曖昧に見えるこの動作の判断基準ってどこだ?
- Posted at:
- 2007/07/02 00:16:09
- 2 Comments
- 0 TrackBacks
- Trackback:
- http://humming.via-kitchen.com/2007/07/02/when-foreign-key-is-added/trackback/
TrackBacks
まだ登録されていません。
Comments
ymasuda
ちょっとコードを追いかけてみましたが、モデルクラス(+α)の名前から決まるhash値で、OyaとKo/Kodomoクラスのどちらが先に並ぶかによって、外部キー制約が付くか付かないかが決まってしまいます。(事実上制御できないですね。)現状、外部キー制約は「おまけ」と考えざるをえないようです。
nobu
返事が遅くなってしまい申し訳ありません。
わざわざ調べてくださってありがとうございます。
やはりランダムに決められてしまうんですね。どちらか一方のみだったらまだ良いと思いますが、どちらになるか分からない。ってのは正直つらいですね。
改善されるまでは重要な所はデータベースを作っておいてinspectdbしてから整形するようにした方がよいのでしょうか?