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:

python 复制代码
plan = models.ForeignKey(
    InventoryCheckPlan,
    on_delete=models.CASCADE,
    related_name='tasks',
)

Django 会默认生成数据库字段:

sql 复制代码
plan_id BIGINT

所以 ORM 查询:

python 复制代码
InventoryCheckTask.objects.filter(
    plan_id=1
)

实际 SQL:

sql 复制代码
SELECT *
FROM wms_inventory_check_task
WHERE plan_id = 1;

但是你的数据库表:

sql 复制代码
SHOW COLUMNS FROM wms_inventory_check_task;

可能没有:

复制代码
plan_id

2. 检查数据库表

执行:

sql 复制代码
DESC wms_inventory_check_task;

正常应该看到:

复制代码
+--------------+------------+
| Field        | Type       |
+--------------+------------+
| id           | bigint     |
| plan_id      | bigint     |
| location_id  | int        |
| assignee_id  | bigint     |
| status       | smallint   |
+--------------+------------+

如果没有 plan_id,就是数据库和 Model 不一致。


3. 解决方式一(推荐):执行 migration

查看 migration:

bash 复制代码
python manage.py makemigrations

然后:

bash 复制代码
python manage.py migrate

Django 会创建:

sql 复制代码
ALTER TABLE wms_inventory_check_task
ADD COLUMN plan_id BIGINT NOT NULL;

4. 解决方式二:数据库已经手动创建

如果你之前是手写 SQL 创建表:

例如:

sql 复制代码
CREATE TABLE wms_inventory_check_task(
    id BIGINT,
    plan BIGINT
);

错误。

应该是:

sql 复制代码
plan_id BIGINT NOT NULL

因为 Django ForeignKey:

python 复制代码
plan = models.ForeignKey(...)

数据库字段不是:

复制代码
plan

而是:

复制代码
plan_id

5. 如果字段实际叫 plan

比如你的表:

sql 复制代码
CREATE TABLE wms_inventory_check_task(
    id BIGINT,
    plan BIGINT
)

可以告诉 Django:

python 复制代码
plan = models.ForeignKey(
    InventoryCheckPlan,
    db_column='plan',
    on_delete=models.CASCADE
)

这样 Django 查询:

sql 复制代码
WHERE plan = 1

而不是:

sql 复制代码
WHERE plan_id = 1

但是一般不推荐,因为 Django 规范就是:

复制代码
xxx_id

6. 如果 migration 状态混乱

查看:

bash 复制代码
python manage.py showmigrations

例如:

复制代码
[X] 0001_initial
[X] 0002_add_task

显示已经执行,但是数据库没有字段。

说明:

migration 记录存在,但是数据库结构不一致。

可以:

开发环境

bash 复制代码
python manage.py migrate app_name zero
python manage.py migrate

生产环境

不要回滚,手动补字段:

sql 复制代码
ALTER TABLE wms_inventory_check_task
ADD COLUMN plan_id BIGINT NOT NULL;

然后补外键:

sql 复制代码
ALTER TABLE wms_inventory_check_task
ADD CONSTRAINT fk_task_plan
FOREIGN KEY(plan_id)
REFERENCES wms_inventory_check_plan(id);

结合你前面的 Model

你的表应该至少包含:

sql 复制代码
id
plan_id
location_id
assignee_id
status

现在错误说明:

text 复制代码
plan_id 缺失

所以第一步直接执行:

sql 复制代码
DESC wms_inventory_check_task;

看一下字段。

大概率是你之前手动建表时把:

sql 复制代码
plan_id

写成了:

sql 复制代码
plan

或者漏掉了。

相关推荐
IvorySQL8 分钟前
PostgreSQL 日报 | JOIN 与外键优化(8 月 9 日)
数据库·postgresql
ltl26 分钟前
自治数据库十年回顾:Peloton、NoisePage、OtterTune 到云原生 auto-tuning
数据库
灯澜忆梦2 小时前
【MySQL10】进阶篇 | 索引_#2性能优化
数据库·sql·mysql·性能优化
C++ 老炮儿的技术栈4 小时前
从 Qt Designer 属性编辑器的层级可以看到继承链
c语言·数据库·c++·qt·sqlite·visual studio
MC皮蛋侠客4 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis
zt1985q5 小时前
本地部署开源网络书签与内容管理工具 Karakeep 并实现外部访问
运维·服务器·网络·数据库·网络协议·开源
IvorySQL6 小时前
PostgreSQL 日报| PostgreSQL 19 默认 WAL 压缩算法(8 月 8 日)
数据库·postgresql·区块链
油丶酸萝卜别吃7 小时前
MySQL B+ 树查询全过程详解
数据库·mysql
leisoo80977 小时前
股票数据本地化存储实战:JSON、数据库与列式存储的方案对比
jvm·数据库·json
Exclusive_Cat7 小时前
MySQL回表机制解析与优化策略
数据库·sql