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
相关产品推荐
相关产品推荐

