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

Django表单中__init__方法生成的choices无法加载问题排查

问题分析与解决方案

让我一步步帮你排查问题:

1. 表单不显示的核心原因:GET请求未传递form到模板

看你的视图else分支(处理GET请求):你创建了表单实例,但没有把它添加到context字典里就传给模板了!模板里的{{ form|crispy }}找不到form变量,自然什么都渲染不出来。

2. 次要问题:表单字段初始化方式不规范

你在__init__里重新创建了objective字段,虽然能生成choices,但会丢失原字段的配置(比如你定义的label),直接修改现有字段的choices更稳妥。

3. 潜在问题:context未初始化

你的代码开头直接写context['assessment'] = assessment,但如果没先初始化context = {},会抛出NameError,虽然你说没报错,但最好显式初始化避免隐患。


修复后的代码

视图代码(关键修改处标了注释)

def newobjtoassess(request, assess_pk):
    user = request.user
    assessment = Assessment.objects.get(pk=assess_pk)
    course_pk = assessment.course.pk
    context = {'assessment': assessment}  # 显式初始化context字典
    form = ObjToAssessmentForm(user=user, course_pk=course_pk)
    if request.method == 'POST':
        print("ok")
        form = ObjToAssessmentForm(request.POST, user=user, course_pk=course_pk)
        if form.is_valid():
            f = form.cleaned_data
            objective = f.get('objective')
            assessment.objectives.add(objective)
            assessment.save()
            return HttpResponseRedirect(reverse('gradebook:assessupdate', args=[assess_pk]))
        else:
            context['form'] = form
            return render(request, "gradebook/newobjtoassess.html", context)
    else:
        print("else")
        form = ObjToAssessmentForm(user=user, course_pk=course_pk)
        context['form'] = form  # 把form加入context,模板才能拿到
        return render(request, "gradebook/newobjtoassess.html", context)

表单类代码(简化字段修改逻辑)

class ObjToAssessmentForm(forms.Form):
    objective = forms.ChoiceField(label='Learning Objective', choices=[])
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        my_course = kwargs.pop('course_pk')
        super().__init__(*args, **kwargs)  # 使用Python3的简化super写法
        choices = [(o.id, str(o)) for o in Objective.objects.filter(user=user, course=my_course)]
        print(choices)
        self.fields['objective'].choices = choices  # 直接修改现有字段的choices,保留原配置

为什么之前的print("ok")没输出?

因为GET请求时表单根本没渲染出来,你没法提交POST请求,自然进入不了POST分支,print("ok")也就不会执行。修复表单显示问题后,你提交表单就能触发POST请求,看到这个打印了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:49:08