Django ModelForm GET提交时提交按钮点击无响应问题排查
问题根因
- FormView默认仅在POST请求中执行表单校验、逻辑处理逻辑,你使用GET方法提交表单时,走的是默认的
get()方法,只会渲染空表单,完全不会处理你提交的查询参数,所以点击提交看不到任何效果。 - 自定义的三个
ModelMultipleChoiceField用法错误:该字段要求queryset返回模型实例(带主键值),但你用values_list(flat=True)返回的是纯字段值列表,会导致表单校验直接失败,就算请求走到校验逻辑也会被判定为无效输入。 - GET表单不需要添加
{% csrf_token %},CSRF校验仅针对会修改服务端数据的POST/PUT/DELETE请求,添加后会把csrf参数混入查询串,属于冗余代码。 - 视图未配置查询结果处理逻辑:既没有重写GET方法处理参数、过滤数据库数据,也没有配置
form_valid的跳转/返回逻辑,就算表单校验通过也不会返回查询结果。 - 提交按钮上的
action=""是无效属性,action仅在<form>标签上生效,写在input标签上没有任何作用,属于冗余错误代码。
修正方案
1. 修改视图层 views.py
重写get()方法处理GET提交的查询参数,完成表单校验、数据库过滤,把结果传递给模板:
from django.views.generic import FormView from .forms import StLouisCitySale208Form from .models import StLouisCitySale208 class StLouisCitySale208View(FormView): form_class = StLouisCitySale208Form template_name = 'maps/StlouiscitySale208.html' success_url = '.' def get(self, request, *args, **kwargs): form = self.get_form() search_results = None # 携带查询参数时执行筛选 if request.GET: if form.is_valid(): filter_kwargs = {} # 处理多选字段,用__in规则匹配 multi_value_fields = ['landuse', 'neighborho', 'policedist'] for field in multi_value_fields: field_val = form.cleaned_data.get(field) if field_val: filter_kwargs[f'{field}__in'] = field_val # 处理单值字段 single_value_fields = ['precinct20','vacantland', 'ward20', 'zip', 'zoning','numbldgs', 'numunits'] for field in single_value_fields: field_val = form.cleaned_data.get(field) if field_val: filter_kwargs[field] = field_val # 执行数据库查询 search_results = StLouisCitySale208.objects.filter(**filter_kwargs) # 传递表单和结果到模板 return self.render_to_response( self.get_context_data(form=form, results=search_results) )
2. 修改表单层 forms.py
把三个选纯字段值的多选框从ModelMultipleChoiceField换成普通MultipleChoiceField,传入正确的选项列表:
from django import forms from .models import StLouisCitySale208 from django.forms import ModelForm class StLouisCitySale208Form(ModelForm): required_css_class = 'form-group' landuse = forms.MultipleChoiceField( label='Land use', widget=forms.SelectMultiple, choices=[(v, v) for v in StLouisCitySale208.objects.values_list('landuse', flat=True).distinct() if v] ) neighborho = forms.MultipleChoiceField( label='Neighborhood', widget=forms.SelectMultiple, choices=[(v, v) for v in StLouisCitySale208.objects.values_list('neighborho', flat=True).distinct() if v] ) policedist = forms.MultipleChoiceField( label='Police district', widget=forms.SelectMultiple, choices=[(v, v) for v in StLouisCitySale208.objects.values_list('policedist', flat=True).distinct() if v] ) class Meta: model = StLouisCitySale208 fields = ['landuse', 'neighborho', 'policedist', 'precinct20','vacantland', 'ward20', 'zip', 'zoning','asmtimprov', 'asmtland', 'asmttotal', 'frontage', 'landarea','numbldgs', 'numunits']
3. 修改前端模板
删除冗余的CSRF标签和无效属性,新增结果展示区块:
<form role="form" action="" method="GET" id="form-map" class="form-map form-search"> <h2>Search Properties</h2> {{ form.as_p }} <input type="submit" class="btn btn-default" value="Submit"> <input type="reset" class="btn btn-default" value="Reset"> </form> <!-- 搜索结果展示区 --> {% if results is not None %} <h3>匹配结果:共{{ results|length }}条记录</h3> <ul> {% for record in results %} <li> 土地用途:{{ record.landuse }} | 所属社区:{{ record.neighborho }} | 警区:{{ record.policedist }} </li> {% empty %} <li>未查询到符合筛选条件的记录</li> {% endfor %} </ul> {% endif %}
4. 路由配置优化
给路由路径末尾添加斜杠,符合Django默认路由规范,避免跳转丢失GET参数:
urlpatterns = [ path("maps/stlouiscitysale208/",StLouisCitySale208View.as_view(),name="stlouiscitysale208"), path('maps/coming_soon/', ComingSoonView.as_view(), name="coming_soon") ]
补充说明:如果需要对
asmtimprov、asmtland这类数值字段做区间筛选(如价格大于/小于某个值、面积在指定范围),不要直接使用模型映射的表单字段,可以单独自定义范围输入字段,在视图过滤时拼接__gte、__lte等查询规则即可。
内容的提问来源于stack exchange,提问作者user18281824
相关产品推荐
相关产品推荐

