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

Django表单实现字段联动过滤:选城市后过滤关联字段

Django表单实现城市与对象名称的联动过滤

核心需求是实现「选择城市后,自动过滤对象名称下拉选项」,这需要后端提供数据接口配合前端AJAX完成,分以下几步操作:

1. 模型优化(可选但建议)

如果ArkiTwoObject是通过一对一关联ArkiOneObject,先给ArkiOneObject加唯一约束,避免同一城市下出现重复的对象名称——否则一对一关联会产生数据冲突:

class ArkiOneObject(models.Model):
    city = models.CharField(max_length=100, verbose_name="城市")
    nameobject = models.CharField(max_length=200, verbose_name="对象名称")

    class Meta:
        unique_together = ('city', 'nameobject')  # 确保同一城市的对象名称唯一

class ArkiTwoObject(models.Model):
    arki_one = models.OneToOneField(ArkiOneObject, on_delete=models.CASCADE, verbose_name="关联对象")
    # 你的其他业务字段...

如果是ArkiTwoObject单独存储city和nameobject字段(不关联ArkiOneObject),模型可保持原样,但需自行承担数据冗余的风险。

2. 定义联动表单

创建FormTwo时,单独拆分city和nameobject为下拉字段,方便后续联动逻辑处理:

from django import forms
from .models import ArkiOneObject, ArkiTwoObject

class FormTwo(forms.ModelForm):
    city = forms.ChoiceField(choices=[], required=True, verbose_name="城市")
    nameobject = forms.ChoiceField(choices=[], required=True, verbose_name="对象名称")

    class Meta:
        model = ArkiTwoObject
        fields = ['city', 'nameobject', ...]  # 补充你的其他业务字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 初始化城市选项:去重获取所有城市
        self.fields['city'].choices = [(city, city) for city in ArkiOneObject.objects.values_list('city', flat=True).distinct()]
        
        # 编辑页面初始化:加载已选城市对应的对象名称
        if self.instance.pk:
            target_arki = self.instance.arki_one
            self.fields['city'].initial = target_arki.city
            name_options = [(obj.nameobject, obj.nameobject) for obj in ArkiOneObject.objects.filter(city=target_arki.city)]
            self.fields['nameobject'].choices = name_options
            self.fields['nameobject'].initial = target_arki.nameobject

3. 后端AJAX接口实现

编写视图函数,接收选中的城市参数,返回该城市下的所有对象名称:

from django.http import JsonResponse
from .models import ArkiOneObject

def get_nameobjects_by_city(request):
    selected_city = request.GET.get('city')
    if not selected_city:
        return JsonResponse({'choices': []})
    
    # 过滤并提取目标城市的对象名称
    name_list = ArkiOneObject.objects.filter(city=selected_city).values_list('nameobject', flat=True)
    # 转换为下拉框所需的选项格式
    choices = [(name, name) for name in name_list]
    return JsonResponse({'choices': choices})

在urls.py中配置接口路由:

from django.urls import path
from .views import get_nameobjects_by_city, form_two_view  # 替换为你的表单视图

urlpatterns = [
    path('form-two/', form_two_view, name='form_two'),
    path('get-nameobjects/', get_nameobjects_by_city, name='get_nameobjects'),
]

4. 前端JS联动逻辑

在表单模板中添加JavaScript,监听城市下拉框的变化,通过AJAX更新对象名称选项:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const citySelect = document.getElementById('id_city');
    const nameSelect = document.getElementById('id_nameobject');

    // 监听城市选择事件
    citySelect.addEventListener('change', function() {
        const city = this.value;
        // 清空对象名称选项
        nameSelect.innerHTML = '<option value="">请选择对象名称</option>';
        
        if (!city) return;

        // 发送AJAX请求获取对应城市的对象名称
        fetch(`{% url 'get_nameobjects' %}?city=${encodeURIComponent(city)}`)
            .then(res => res.json())
            .then(data => {
                // 动态添加新选项
                data.choices.forEach(item => {
                    const option = document.createElement('option');
                    option.value = item[0];
                    option.textContent = item[1];
                    nameSelect.appendChild(option);
                });
            })
            .catch(err => console.log('加载对象名称失败:', err));
    });

    // 编辑页面自动触发一次选择事件,加载已选城市的对象名称
    if (citySelect.value) {
        citySelect.dispatchEvent(new Event('change'));
    }
});
</script>

5. 表单提交处理

在表单视图中,将选中的城市和对象名称关联到ArkiOneObject实例,再保存ArkiTwoObject:

def form_two_view(request):
    if request.method == 'POST':
        form = FormTwo(request.POST)
        if form.is_valid():
            city = form.cleaned_data['city']
            name = form.cleaned_data['nameobject']
            # 获取对应的ArkiOneObject实例
            arki_one_instance = ArkiOneObject.objects.get(city=city, nameobject=name)
            # 保存ArkiTwoObject并关联实例
            arki_two = form.save(commit=False)
            arki_two.arki_one = arki_one_instance
            arki_two.save()
            # 跳转至成功页面或添加提示
            return redirect('your_success_url')
    else:
        form = FormTwo()
    return render(request, 'your_form_template.html', {'form': form})

如果是ArkiTwoObject直接存储city和nameobject字段,直接调用form.save()即可,无需额外关联处理。


内容的提问来源于stack exchange,提问作者Денис

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:35:57