Ami*_*irM 5 mysql django django-models legacy-database composite-primary-key
我有一个遗留数据库,其中一些表包含复合主键.我通过运行manage.py inspectdb
命令得到的模型看起来像这样.
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'),)
Run Code Online (Sandbox Code Playgroud)
我可以正常获取数据.但是,当我想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'}
Run Code Online (Sandbox Code Playgroud)
但是我需要:
{'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'}
Run Code Online (Sandbox Code Playgroud)
由于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 | |
+------------+------------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)
不幸的是django还没有复合主键(复合主键也称为多列主键)
有一个第三方库,毫不奇怪地命名为django-compositekey,它可以创建具有多列主键的模型。然而,该项目没有维护,并且与最新版本的 django 不兼容。
最好的选择是在表中添加一个新列,该列是一个自动字段,并使其成为新的主键。目前构成主键的字段可以被标记为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;
Run Code Online (Sandbox Code Playgroud)
然后编辑您的模型并从这些字段中删除primary_key=True 标志。
脚注:
某些数据库(例如 sqlite)不LIKE
支持CREATE TABLE
. 在这些情况下,您将必须查找原始表的创建表语句,并在编辑表名称后复制粘贴。从你的表结构来看,你似乎正在使用 mysql 并且它支持该LIKE
子句。
归档时间: |
|
查看次数: |
3158 次 |
最近记录: |