Django ModelForm如何添加“All”选项以取消过滤返回全部数据
Django ModelForm 增加「全部」选项实现过滤开关
实现步骤
1. 改造ModelForm,追加全量查询选项
默认ModelForm生成的model_name字段不会自带全选选项,直接覆盖字段定义,手动拼接选项即可:
from django import forms from .models import TruckTrip class TruckTripForm(forms.ModelForm): # 构造选项列表,首项为全量查询选项 MODEL_CHOICES = [("all", "全部车型")] # 若model_name是预设choices的普通字段,直接拼接原有选项 # MODEL_CHOICES += TruckTrip._meta.get_field('model_name').choices # 若model_name是外键字段,动态拉取关联表数据生成选项 # MODEL_CHOICES += [(truck_model.pk, str(truck_model)) for truck_model in TruckModel.objects.all()] model_name = forms.ChoiceField( choices=MODEL_CHOICES, required=False, initial="all", # 默认选中全部选项 label="车型" ) class Meta: model = TruckTrip fields = ["model_name"]
2. 调整视图过滤逻辑
对提交的字段值做判断,只有选中非all的具体值时才触发过滤,同时统一走表单校验逻辑,避免直接读取原始GET参数带来的异常:
def table(request): trips = TruckTrip.objects.all() # 绑定GET参数,无参数时用默认初始值 form = TruckTripForm(request.GET or None) if form.is_valid(): selected_model = form.cleaned_data.get("model_name") # 选中具体车型时才加过滤条件 if selected_model and selected_model != "all": trips = trips.filter(model_name=selected_model) context = { "form": form, "trips": trips } return render(request, "tripweight/index.html", context)
简化写法
如果不需要显式展示all字样,也可以把首选项值设为空字符串("", "全部车型"),视图层可以省略!= "all"的判断,只要selected_model有真值就执行过滤,逻辑更简洁:
# 表单选项改法 MODEL_CHOICES = [("", "全部车型")] # 视图过滤逻辑改法 if selected_model: trips = trips.filter(model_name=selected_model)
注意事项
- 不要直接读取
request.GET的原始参数做查询,必须经过表单cleaned_data取值,自动过滤非法入参 - 外键场景下选项值用关联模型主键即可,和字符串类型的
all/空值不会产生冲突 - 模板层正常渲染表单字段即可,不需要额外修改提交逻辑,GET提交会自动把选中值拼接到url参数里
内容的提问来源于stack exchange,提问作者Peter Sugrobov
相关产品推荐
相关产品推荐

