You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django递归模型部署Heroku出现core_menuoption关系不存在错误如何解决

根本原因

你的问题和递归外键没有关系,报错是模块导入阶段提前执行了数据库查询导致的:
从报错栈可以看到,你在执行migrate命令时,Django会先加载项目的URL配置,进而导入MenuOptionForm类,而你在表单的Meta类的widget定义里直接写了choices=[(m, m) for m in MenuOption.objects.all()],这段代码会在导入表单类的瞬间就执行数据库查询,此时migrate命令还没完成表结构创建,自然会报core_menuoption表不存在的错误。
本地运行正常是因为你本地的数据库表已经提前创建完成,导入阶段的查询可以正常返回结果。

可行解决方案

方案1(最推荐,无冗余代码)

直接删除widget中的自定义choices参数即可。Django的ModelForm针对外键字段默认会使用ModelChoiceField,会自动在表单实例化阶段动态拉取对应模型的所有数据作为选项,不需要手动指定choices:

class MenuOptionForm(forms.ModelForm):
    class Meta:
        model = MenuOption
        fields = ('parent', 'title')
        widgets = {
            # 删掉多余的choices参数
            'parent': forms.Select(attrs={'class': 'form-control mb-1'}),
            # 顺便修复你代码里少写的引号语法错误
            'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'title'})
        }

方案2(需要自定义choices时使用)

如果确实需要自定义choices的生成逻辑,把查询逻辑放到表单的__init__方法中,确保只有表单实例化的时候才执行查询,不会在模块导入阶段触发:

class MenuOptionForm(forms.ModelForm):
    class Meta:
        model = MenuOption
        fields = ('parent', 'title')
        widgets = {
            'parent': forms.Select(attrs={'class': 'form-control mb-1'}),
            'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'title'})
        }
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 动态设置choices,仅在表单实例化时执行查询
        self.fields['parent'].choices = [(m, m) for m in MenuOption.objects.all()]

方案3(临时应急,不推荐长期使用)

如果暂时不想修改代码,可以临时调整部署流程:先把MenuOptionForm中查询相关的代码注释掉,部署到Heroku完成migrate之后,再恢复代码重新部署一次。但这个方案只是临时解决,后续如果清空数据库或者重新部署还会遇到同样的问题。


内容的提问来源于stack exchange,提问作者D4NieLDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 17:54:04