Django Admin中如何通过下拉框值联动筛选城市选项?
Django Admin实现地址表单的州/省-城市联动筛选
先修正你代码里的基础问题
- 模型拼写错误:
Adrress改为Address,City模型里的cityـname存在特殊字符,改为city_name,避免后续字段调用出错。 - 之前的自定义Widget方案存在硬编码数据、JS操作逻辑错误等问题,改用AJAX动态获取数据的方式更可靠。
步骤1:添加AJAX接口获取对应州的城市
在项目的views.py中添加视图:
from django.http import JsonResponse from .models import City def get_cities_by_state(request): state_id = request.GET.get('state_id') # 根据选中的州ID过滤城市,返回ID和名称 cities = City.objects.filter(state_id=state_id).values('id', 'city_name') return JsonResponse(list(cities), safe=False)
在项目根urls.py中添加路由:
from django.urls import path from . import views urlpatterns = [ # 其他原有路由 path('admin/get-cities/', views.get_cities_by_state, name='get_cities_by_state'), ]
步骤2:自定义Admin表单
在forms.py中编写表单,添加州选择字段并处理初始值:
from django import forms from .models import Address, State, City class AddressAdminForm(forms.ModelForm): # 添加州选择字段,用于触发联动 state = forms.ModelChoiceField( queryset=State.objects.all(), required=True, label="州/省" ) class Meta: model = Address fields = ['user', 'state', 'city', 'description'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 编辑地址时,自动选中对应州并加载城市 if self.instance.pk: self.fields['state'].initial = self.instance.city.state self.fields['city'].queryset = City.objects.filter(state=self.instance.city.state) else: # 新建地址时,默认城市下拉框为空 self.fields['city'].queryset = City.objects.none()
步骤3:修改Admin类并引入JS
在admin.py中更新地址的Admin配置,引入自定义JS:
from django.contrib import admin from .models import State, City, Address from .forms import AddressAdminForm @admin.register(State) class StateAdmin(admin.ModelAdmin): list_display = ('state_name',) @admin.register(City) class CityAdmin(admin.ModelAdmin): list_display = ('city_name', 'state') @admin.register(Address) class AddressAdmin(admin.ModelAdmin): form = AddressAdminForm class Media: # 引入Django Admin自带的jQuery,避免版本冲突 js = ( 'admin/js/jquery.js', 'js/address_city_filter.js', )
步骤4:编写联动JS逻辑
在项目static/js/目录下创建address_city_filter.js:
(function($) { $(document).ready(function() { const stateSelect = $('#id_state'); const citySelect = $('#id_city'); // 监听州选择变化 stateSelect.change(function() { const stateId = $(this).val(); if (stateId) { $.ajax({ url: '/admin/get-cities/', data: { 'state_id': stateId }, dataType: 'json', success: function(data) { citySelect.empty(); citySelect.append('<option value="">请选择城市</option>'); $.each(data, function(index, city) { citySelect.append(`<option value="${city.id}">${city.city_name}</option>`); }); }, error: function() { citySelect.empty(); citySelect.append('<option value="">加载城市失败</option>'); } }); } else { citySelect.empty(); citySelect.append('<option value="">请先选择州/省</option>'); } }); // 页面加载时,若有默认州则触发一次联动 if (stateSelect.val()) { stateSelect.trigger('change'); } }); })(django.jQuery);
最后部署注意事项
- 运行
python manage.py collectstatic,将静态文件收集到指定目录 - 确保所有模型字段名的拼写错误已修正
- 测试新增/编辑地址时的联动效果
内容的提问来源于stack exchange,提问作者user25495429
相关产品推荐
相关产品推荐

