Git克隆Django项目后报错django.db.utils.OperationalError: no such table: price_category
根因定位
你的错误核心是模块级别的数据库查询代码在Django完成启动、数据库表迁移前就被执行了:
看forms.py里的代码是写在全局作用域的,不属于任何类或函数:
choices= Category.objects.all().values_list('name', 'name') for item in choices: choice_list.append(item)
Django启动(包括执行runserver、migrate等任何管理命令)时,会先导入所有应用的模块,这时候上述代码会直接触发对price_category表的查询。
- 电脑A的数据库已经提前执行过迁移,存在
price_category表,所以查询能成功,没有报错 - 电脑B是全新环境,还没创建数据库表,导入阶段就触发查询直接报错,根本没法正常执行
migrate命令完成表创建,进入死循环
临时解决步骤
可先快速解决当前环境无法运行的问题:
- 临时注释掉
forms.py里所有和Category查询、choice_list相关的代码,同时把PriceForm中widgets的category配置行也暂时注释 - 执行
python manage.py migrate完成所有表的创建(包括price_category表) - 把注释的代码恢复,之后即可正常启动服务
永久修复方案
不要把数据库查询放在模块全局作用域,避免后续再出现同类问题,推荐两种修改方式:
方案1:使用Django原生ModelChoiceField(更简洁)
自动加载分类选项,不需要手动查询:
from django import forms from .models import Price, Category class PriceForm(forms.ModelForm): # 重写category字段为ModelChoiceField category = forms.ModelChoiceField( queryset=Category.objects.all(), widget=forms.Select(attrs={'class': 'form-control'}), to_field_name='name' # 提交值取name字段,和原有逻辑对齐 ) class Meta: model= Price fields= ('name', 'price','category') widgets= { 'name': forms.TextInput(attrs={'class': 'form-control'}), }
方案2:把查询逻辑放在表单初始化方法中
如果要保留原有choices写法,将查询移到__init__方法,仅在表单实例化时才执行查询,不会在模块导入阶段触发:
from django import forms from .models import Price, Category class PriceForm(forms.ModelForm): class Meta: model= Price fields= ('name', 'price','category') widgets= { 'name': forms.TextInput(attrs={'class': 'form-control'}), 'category': forms.Select(attrs={'class': 'form-control'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 表单初始化时再加载选项 self.fields['category'].choices = Category.objects.all().values_list('name', 'name')
内容的提问来源于stack exchange,提问作者Kentypop
相关产品推荐
相关产品推荐

