2013-08-06 18 views
2

所以我只測試了一件事情,製作下列表格。Django的inspectdb不會執行ManyToManyField

# Dump of table driverclass 
# ------------------------------------------------------------ 

CREATE TABLE `driverclass` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(20) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

# Dump of table event 
# ------------------------------------------------------------ 

CREATE TABLE `event` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(20) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

# Dump of table driver 
# ------------------------------------------------------------ 

CREATE TABLE `driver` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(20) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

# Dump of table driver_driverclass_event 
# ------------------------------------------------------------ 

CREATE TABLE `driver_driverclass_event` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `driver_id` int(11) unsigned DEFAULT NULL, 
    `event_class_id` int(11) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `driver_id` (`driver_id`), 
    KEY `event_class_id` (`event_class_id`), 
    CONSTRAINT `driver_driverclass_event_ibfk_2` FOREIGN KEY (`event_class_id`) REFERENCES `driverclass_event` (`id`), 
    CONSTRAINT `driver_driverclass_event_ibfk_1` FOREIGN KEY (`driver_id`) REFERENCES `driver` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

# Dump of table driverclass_event 
# ------------------------------------------------------------ 

CREATE TABLE `driverclass_event` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `event_id` int(11) unsigned DEFAULT NULL, 
    `driverclass_id` int(11) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `event_id` (`event_id`), 
    KEY `driverclass_id` (`driverclass_id`), 
    CONSTRAINT `driverclass_event_ibfk_2` FOREIGN KEY (`driverclass_id`) REFERENCES `driverclass` (`id`), 
    CONSTRAINT `driverclass_event_ibfk_1` FOREIGN KEY (`event_id`) REFERENCES `event` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

這應該是ManyToManyField的關係。然而,Djangosinspectdb將它看作是具有大量ForeignKeys的5個模型。請問Djangosinspectdb是否考慮了ManyToManyFields,還是我的databasemodel錯誤?

+0

它輸出了什麼? – Ngenator

+0

5個表與對方的外鍵。 – Martol1ni

回答

4

您的數據庫模式看起來沒問題。但是,Django不會像您發現的那樣自動創建「多對多」字段。 driverclass_事件和** driver_driverclass_event **的模型是所謂的「通過」模型。通常情況下,還要定義ManyToManyField在關係的兩端「到」模型指定正確的:

class Event(db.Model): 
    pass 

class DriverClass(db.Model): 
    events = db.ManyToManyField(Event, through='DriverClassEvent') 

class DriverClassEvent(db.Model): 
    driver_class = db.ForeignKeyField(DriverClass) 
    event = db.ForeignKeyField(Event) 

參見:https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships

通常通過當你想存儲信息車型均採用約爲的關係,如關係的開始日期或使用外鍵引用此關係。在您的示例中,您存儲哪些驅動程序與DriverClassEvent有關係。所以DriverClassEvent應該有一個模型來引用它。

class DriverDriverClassEvent(db.Model): 
    driver = db.ForeignKeyField(Driver) 
    driver_class_event = db.ForeignKeyField(DriverClassEvent) 

class Driver(db.Model): 
    driver_class_events = db.ManyToManyField(DriverClassEvent, through='DriverDriverClassEvent') 

現在你可以放下DriverDriverClassEvent,你不要將任何數據存儲有關的關係,或參考其他車型的關係。所以,最後一個例子變成*:

class Driver(db.Model): 
    driver_class_events = db.ManyToManyField(DriverClassEvent, db_table='driver_driverclass_event') 

*請注意,您不必在字段名控制,所以那些不得不匹配Django的自動生成的字段名。

+0

非常感謝這篇文章。我不確定你是否理解這個模型,但它感覺不太對。我只是試圖將驅動程序連接到某個類和某個事件。另外,在最後一個例子中,我可以編寫ManyToManyField(DriverClassEvent ...而不指定DriverClassEvent的模型嗎? – Martol1ni

+0

另請參閱我的編輯,我對錶名感到困惑 - 您的數據庫模型定義了多對多** driverclass **和** event **,稱爲** driverclass_event **。然後** driverclass_event **和** driver **之間存在關係,稱爲** driver_driverclass_event **。因此,您有3個簡單的有2個關係的實體,得到5個表格和5個模型,看起來你不想有兩個二元關係,而是一個三元關係,這也需要不同的數據庫模式設計。 – bouke