5

我有一個遺留數據庫,其中一些表包含複合主鍵。通過運行manage.py inspectdb命令獲得的模型看起來像這樣。在遺留數據庫中使用django項目中的複合主鍵

class MyTable(models.Model): 
    field1_id = models.IntegerField(db_column='field1id', primary_key=True) 
    is_favorite = models.BooleanField(db_column='isfavorite', default=False, null=False) 
    is_admin = models.BooleanField(db_column='isadmin', default=False, null=False) 
    role = models.IntegerField(default=USER_GUEST, null=False) 
    field2 = models.BooleanField(null=False, default=True) 
    field3 = models.BooleanField(null=False, default=True) 
    is_active = models.BooleanField(db_column='isactive', null=False, default=True) 

    user = models.ForeignKey(
     CustomUser, models.DO_NOTHING, db_column='userid', primary_key=True) 

    class Meta: 
     managed = False 
     db_table = 'mytable' 
     unique_together = (('user', 'field1_id'),) 

我可以正常取數據。但是,當我想在某個模型實例上運行save()命令時出現問題。查詢django執行的是不正確的。例如:

>>> from web_services.apps.my_app.models import MyTable 
>>> g = MyTable.objects.get(field1_id=12) 
>>> g.is_active = True 
>>> g.save() 
>>> connection.queries[-1] 
{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12'} 

但我需要:

{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12' AND `mytable`.`userid` = 1'} 

由於Django不支持複合主鍵,這將是對解決這一問題的最佳解決方案?請注意,這是傳統數據庫表,並沒有AutoField

編輯:增加了傳統的表結構

+------------+------------+------+-----+---------+-------+ 
| Field  | Type  | Null | Key | Default | Extra | 
+------------+------------+------+-----+---------+-------+ 
| userid  | int(11) | NO | PRI | NULL |  | 
| field1id | int(11) | NO | PRI | NULL |  | 
| isfavorite | int(11) | NO |  | 0  |  | 
| isadmin | int(11) | NO |  | 0  |  | 
| role  | int(11) | YES |  | NULL |  | 
| field2  | tinyint(1) | NO |  | 1  |  | 
| field3  | tinyint(1) | NO |  | 1  |  | 
| isactive | tinyint(4) | NO |  | 1  |  | 
+------------+------------+------+-----+---------+-------+ 
+0

如果您添加表格結構,也是最好的。 – e4c5

+0

@ e4c5添加了遺留表格結構 – AmirM

回答

1

不幸的是Django的不not yet have a composite primary key(複合主鍵也被稱爲多列主鍵)

有一個第三方庫,毫不奇怪的名字django-compositekey那使創建具有多列主鍵的模型成爲可能。但是該項目現在保持不變,並且與最新版本的django不兼容。

最好的辦法是在你的表格中添加一個新的列,它是一個AutoField,並將它作爲新的主鍵。然後可以將構成主鍵的字段標記爲unique_together。雖然這可能不是理想的少數查詢。這對大多數人來說已經夠用了。

如果使用當前表結構更新您的問題(如sql控制檯中所示),我將更新我的答案以顯示模型的外觀。

更新 有很多不同的方法可以放棄舊的複合主鍵並將其替換爲新的自動增量主鍵。這是最容易的,它只涉及SQL

CREATE TABLE newtable LIKE mytable; 
ALTER TABLE newtable DROP PRIMARY KEY; 
ALTER TABLE newtable ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY; 
RENAME TABLE mytable to mytable_old; 
RENAME TABLE newtable to mytable; 
INSERT INTO mytable(userid,field1id, rest of the fields) 
    SELECT * FROM mytable_old; 

然後編輯您的模型並從這些字段中刪除primary_key = True標誌。

腳註:
像sqlite的一些數據庫,例如不支持在CREATE TABLELIKE條款。在這些情況下,您必須查找原始表的create table語句,並在編輯表名後複製粘貼。從您的表格結構來看,您似乎在使用mysql,它支持LIKE子句。

+0

雖然它是'純粹的SQL'?我不確定'CREATE TABLE'中的'LIKE'是標準SQL,可能是添加到'純粹MySQL'或類似的東西?(MySQL/MyISAM支持LIKE,但Firebird不支持,不知道其他引擎/ RDMBS) –

+0

@JanSegre你是對的,它不被所有數據庫支持。當我在上面的答案中寫純sql的時候,我只是想不涉及django而不是使用ansi標準。更新我的答案。 – e4c5

0

您必須從模型中刪除managed = False命令才能編輯您的表格

相關問題