Django中如何根据指定模型字段过滤数据并将结果作为表单选择项
Django中如何根据指定模型字段过滤数据并将结果作为表单选择项
看起来你想要实现的是:在Form_Working表单里,根据选中的name_object(类似主键),过滤出CreateNewGPR模型中对应的name_working值,把这些值作为下拉选择项。我来帮你一步步搞定这个需求,分两种场景来实现——一种是页面刷新式的过滤,另一种是更友好的AJAX动态更新(不用刷新页面)。
一、基础实现(页面刷新式)
首先咱们先调整表单和视图,实现基础的过滤功能:
1. 修改表单(forms.py)
咱们需要在Form_Working里添加name_object和name_working字段,并且在初始化时根据传入的name_object过滤选项:
from django import forms from .models import CreateNewGPR, CreateNewWorkDay class Form_Working(forms.ModelForm): # 定义name_object选择框,先获取所有唯一的name_object值 name_object = forms.ChoiceField( choices=[], verbose_name="Наименование объекта", required=True ) # 定义name_working选择框,初始为空,后续填充过滤后的值 name_working = forms.ChoiceField( choices=[], verbose_name="Наименование работы по ГПР", required=True ) class Meta: model = CreateNewWorkDay fields = [ "name_object", "name_working", "second_name_working", "third_name_working", "value_work_fact", "lyudi_fact", "technik_fact", "date_day" ] widgets = { "date_day": forms.DateInput(attrs={"class":"form-control", "type":"date"}) } def __init__(self, *args, **kwargs): # 从参数中取出选中的name_object selected_obj = kwargs.pop('selected_obj', None) super().__init__(*args, **kwargs) # 填充name_object的所有可选值(去重,避免重复选项) obj_choices = CreateNewGPR.objects.values_list('name_object', flat=True).distinct() self.fields['name_object'].choices = [(obj, obj) for obj in obj_choices] # 如果有选中的name_object,过滤对应的name_working if selected_obj: work_choices = CreateNewGPR.objects.filter(name_object=selected_obj).values_list('name_working', flat=True).distinct() self.fields['name_working'].choices = [(work, work) for work in work_choices] # 如果是POST请求,从提交的数据中获取name_object并过滤 elif self.data.get('name_object'): work_choices = CreateNewGPR.objects.filter(name_object=self.data.get('name_object')).values_list('name_working', flat=True).distinct() self.fields['name_working'].choices = [(work, work) for work in work_choices]
2. 修改视图(views.py)
在视图里处理GET和POST请求,传递选中的name_object参数:
from django.shortcuts import render, redirect from .forms import Form_Working def create_work_day(request): if request.method == 'POST': form = Form_Working(request.POST) if form.is_valid(): form.save() # 保存成功后重定向到你想要的页面 return redirect('some_success_url') else: # 从GET参数中获取选中的name_object(比如访问 /create-work-day/?obj=123) selected_obj = request.GET.get('obj') form = Form_Working(selected_obj=selected_obj) return render(request, 'your_template.html', {'form': form})
二、进阶实现(AJAX动态更新,无需刷新页面)
如果想要更流畅的用户体验,咱们可以用AJAX实现选择name_object后,自动更新name_working的选项:
1. 添加AJAX视图(views.py)
新增一个视图用来返回过滤后的name_working选项:
from django.http import JsonResponse from .models import CreateNewGPR def get_working_options(request): name_object = request.GET.get('name_object') if not name_object: return JsonResponse({'options': []}) # 获取该name_object下所有唯一的name_working值 works = CreateNewGPR.objects.filter(name_object=name_object).values_list('name_working', flat=True).distinct() # 整理成前端需要的格式 options = [{'value': work, 'label': work} for work in works] return JsonResponse({'options': options})
2. 配置路由(urls.py)
给新增的AJAX视图添加路由:
from django.urls import path from . import views urlpatterns = [ path('create-work-day/', views.create_work_day, name='create_work_day'), path('get-working-options/', views.get_working_options, name='get_working_options'), # 其他路由... ]
3. 修改模板(your_template.html)
添加JS代码实现动态更新:
<form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">提交表单</button> </form> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script> $(document).ready(function() { // 当name_object选择框变化时触发AJAX请求 $('#id_name_object').change(function() { const selectedObj = $(this).val(); $.ajax({ url: "{% url 'get_working_options' %}", data: {'name_object': selectedObj}, dataType: 'json', success: function(response) { const workingSelect = $('#id_name_working'); // 清空原有选项 workingSelect.empty(); // 添加新选项 $.each(response.options, function(index, item) { workingSelect.append($('<option>', { value: item.value, text: item.label })); }); } }); }); // 页面加载时如果有选中的name_object,自动触发一次更新 const initialObj = $('#id_name_object').val(); if (initialObj) { $('#id_name_object').trigger('change'); } }); </script>
三、优化建议(可选但推荐)
你当前的模型中name_object用的是IntegerField,其实更推荐改成ForeignKey关联到对应的对象模型,这样不仅符合Django ORM的设计规范,还能避免无效的数值输入,比如:
# models.py class Object(models.Model): name = models.CharField(verbose_name="Наименование объекта", max_length=255) # 其他相关字段... class CreateNewGPR(models.Model): name_object = models.ForeignKey(Object, on_delete=models.CASCADE, verbose_name="Наименование объекта") # 其他字段不变...
对应的表单里的name_object字段可以改成ModelChoiceField,更方便选择:
name_object = forms.ModelChoiceField( queryset=Object.objects.all(), verbose_name="Наименование объекта", required=True )
内容来源于stack exchange
相关产品推荐
相关产品推荐

