You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 14:34:53