Django运行报no such column: Blog_post.category_id错误排查
问题说明
为Post模型新增Category分类外键关联后,执行makemigrations、migrate命令仍触发数据库报错:
no such column: Blog_post.category_id
访问站点根路径时抛出OperationalError异常。疑问点为该故障是否属于模型层问题,是否需要补充views.py逻辑。
故障原因
该问题和views层业务逻辑无关,完全是模型定义错误+迁移未正确生效导致,具体问题点:
- 模型类缩进错误:
models.py中__str__、get_absolute_url两个方法没有缩进在Post类内部,属于全局函数,Django无法正确解析Post模型结构 - 外键配置非法:
category外键的default参数传入了字符串"Some random thing",但ForeignKey字段的默认值必须是关联的Category实例、或Category主键的数值,字符串值不合法,直接导致迁移生成的SQL逻辑异常 - 数据库表结构未更新:由于上述模型错误,虽然执行了迁移命令,但实际并没有在Blog_post表中生成
category_id列,查询时自然会报列不存在的错误 - 附带代码瑕疵:views.py中重复定义了两次PostListView类,后者会覆盖前者;存在无用导入
from unicodedata import category;Post创建、更新视图的fields列表未包含category字段,后续无法在编辑页设置分类。
修复方案
- 修正models.py代码,调整方法缩进、修复外键配置,参考代码如下:
from django.db import models from django.urls import reverse class Category(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Post(models.Model): # 若Post表已有存量数据,可给字段加null=True允许空值,或提前创建一个默认分类作为默认值 category = models.ForeignKey(Category, on_delete=models.CASCADE) werkstoffnummer = models.CharField(max_length=100) # 保留原Post模型的其他字段(werkstoffbezeichnung、date_posted、author等) def __str__(self): return self.werkstoffnummer def get_absolute_url(self): return reverse("post-detail", kwargs={"pk": self.pk})
注意:如果存量Post数据较多,新增非空外键时建议先设置null=True,后续再给历史数据补充分类,避免迁移时卡住要求输入默认值。
- 清理异常迁移文件:进入Blog应用的migrations目录,删除除
__init__.py之外的所有旧迁移文件 - 重新执行迁移命令,在项目根目录终端依次运行:
python manage.py makemigrations python manage.py migrate
- 修正views.py的问题:
- 删除重复定义的第二个PostListView类,保留对应路由需要的定义即可
- 删除无用导入
from unicodedata import category - 在PostCreateView、PostUpdateView的fields列表中添加
"category"字段,确保编辑文章时可以选择分类,示例:
PostUpdateView的fields列表做相同修改即可。class PostCreateView(LoginRequiredMixin, CreateView): model = Post fields = [ "werkstoffnummer", "werkstoffbezeichnung", "category" ] # 原有form_valid等逻辑保持不变
内容的提问来源于stack exchange,提问作者Zak Meshou
相关产品推荐
相关产品推荐

