Django中request.POST数据无法传入form.data的问题
问题:Django表单实例化后form.data为空,request.POST却包含对应字段
我定义了DPStatusForm表单类,在视图update_status中传入request.POST实例化表单,但调试发现request.POST包含status键值,form.data却为空。具体代码及调试输出如下:
表单代码
class DPStatusForm(forms.Form): status = forms.ChoiceField(label="") def __init__(self, excluded_choice=None, *args, **kwargs): super().__init__(*args, **kwargs) if excluded_choice: status_choices = ( (s.value, s.label) for s in DP.Status if s.value != excluded_choice ) else: status_choices = ((s.value, s.label) for s in DP.Status) self.fields["status"].choices = status_choices
视图代码
def update_status(request, id): if request.method == "GET": return redirect("my_app:show_dp", id) p = get_object_or_404(DP, pk=id) form = DPStatusForm(request.POST) # debug statements print(request.POST) print(form.data) # ...
调试输出
# request.POST <QueryDict: {'csrfmiddlewaretoken': ['xxx...], 'status': ['1']}> # form.data <MultiValueDict: {}>
原因及解决方法
原因
问题出在你给status字段赋值的choices是生成器表达式。Django表单初始化时会验证传入数据是否在可选范围内,而生成器只能被遍历一次,后续表单处理流程中无法再次读取选项,导致表单无法正确解析request.POST中的数据,最终form.data为空。
解决方法
把生成器表达式改成列表,让选项数据可以被多次访问:
修改后的表单代码:
class DPStatusForm(forms.Form): status = forms.ChoiceField(label="") def __init__(self, excluded_choice=None, *args, **kwargs): super().__init__(*args, **kwargs) if excluded_choice: status_choices = [ (s.value, s.label) for s in DP.Status if s.value != excluded_choice ] else: status_choices = [(s.value, s.label) for s in DP.Status] self.fields["status"].choices = status_choices
核心改动是将生成器的()替换为列表的[],这样choices会被存储为可重复遍历的列表,表单就能正常识别request.POST中的status值,form.data也会被正确填充。
内容的提问来源于stack exchange,提问作者kyuden
相关产品推荐
相关产品推荐

