django外键字段会自动在数据库字段后面加上_id
这个错误:
(1054, "Unknown column 'wms_inventory_check_task.plan_id' in 'where clause'")表示:
Django 查询
wms_inventory_check_task表时,SQL 使用了plan_id字段,但是你的 MySQL 表中不存在plan_id这个列。
1. 产生原因
你的 Django Model:
plan=models.ForeignKey(InventoryCheckPlan,on_delete=models.CASCADE,related_name='tasks',)Django 会默认生成数据库字段:
plan_idBIGINT所以 ORM 查询:
InventoryCheckTask.objects.filter(plan_id=1)实际 SQL:
SELECT*FROMwms_inventory_check_taskWHEREplan_id=1;但是你的数据库表:
SHOWCOLUMNSFROMwms_inventory_check_task;可能没有:
plan_id2. 检查数据库表
执行:
DESCwms_inventory_check_task;正常应该看到:
+--------------+------------+ | Field | Type | +--------------+------------+ | id | bigint | | plan_id | bigint | | location_id | int | | assignee_id | bigint | | status | smallint | +--------------+------------+如果没有plan_id,就是数据库和 Model 不一致。
3. 解决方式一(推荐):执行 migration
查看 migration:
python manage.py makemigrations然后:
python manage.py migrateDjango 会创建:
ALTERTABLEwms_inventory_check_taskADDCOLUMNplan_idBIGINTNOTNULL;4. 解决方式二:数据库已经手动创建
如果你之前是手写 SQL 创建表:
例如:
CREATETABLEwms_inventory_check_task(idBIGINT,planBIGINT);错误。
应该是:
plan_idBIGINTNOTNULL因为 Django ForeignKey:
plan=models.ForeignKey(...)数据库字段不是:
plan而是:
plan_id5. 如果字段实际叫 plan
比如你的表:
CREATETABLEwms_inventory_check_task(idBIGINT,planBIGINT)可以告诉 Django:
plan=models.ForeignKey(InventoryCheckPlan,db_column='plan',on_delete=models.CASCADE)这样 Django 查询:
WHEREplan=1而不是:
WHEREplan_id=1但是一般不推荐,因为 Django 规范就是:
xxx_id6. 如果 migration 状态混乱
查看:
python manage.py showmigrations例如:
[X] 0001_initial [X] 0002_add_task显示已经执行,但是数据库没有字段。
说明:
migration 记录存在,但是数据库结构不一致。
可以:
开发环境
python manage.py migrate app_name zero python manage.py migrate生产环境
不要回滚,手动补字段:
ALTERTABLEwms_inventory_check_taskADDCOLUMNplan_idBIGINTNOTNULL;然后补外键:
ALTERTABLEwms_inventory_check_taskADDCONSTRAINTfk_task_planFOREIGNKEY(plan_id)REFERENCESwms_inventory_check_plan(id);结合你前面的 Model
你的表应该至少包含:
id plan_id location_id assignee_idstatus现在错误说明:
plan_id 缺失所以第一步直接执行:
DESCwms_inventory_check_task;看一下字段。
大概率是你之前手动建表时把:
plan_id写成了:
plan或者漏掉了。
