Django Admin中基于选中Province过滤City字段(新手求助)
Django Admin实现省市级联下拉的方案
针对你的模型结构,要实现选完省份后城市只显示对应省份的选项,下面给两种可行方案,新手可以按需选择:
方案一:手动实现(理解底层逻辑)
1. 完善City模型的显示
给City模型加个__str__方法,避免Admin里城市显示成无意义的对象:
class City(models.Model): province = models.ForeignKey("election.Province", on_delete=models.CASCADE) name = models.CharField(max_length=70, unique=True, null=True, blank=True,) def __str__(self): return self.name
2. 编写获取城市的视图
在election/views.py中添加视图,接收省份ID并返回对应城市的JSON数据:
from django.http import JsonResponse from .models import City def get_cities(request): province_id = request.GET.get('province_id') cities = City.objects.filter(province_id=province_id).values('id', 'name') return JsonResponse(list(cities), safe=False)
3. 配置URL路由
在election/urls.py中添加视图对应的路由:
from django.urls import path from . import views urlpatterns = [ # 其他已有路由... path('get-cities/', views.get_cities, name='get_cities'), ]
同时确保项目根目录的urls.py包含了election的路由:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('election/', include('election.urls')), ]
4. 自定义Admin模板添加JS联动逻辑
创建模板文件templates/admin/election/election/change_form.html(路径对应你的app和模型名),继承默认Admin修改页面并添加AJAX联动代码:
{% extends "admin/change_form.html" %} {% block extrahead %} {{ block.super }} <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(function() { const $province = $('#id_province'); const $city = $('#id_city'); // 页面加载时,未选省份则清空城市选项 if (!$province.val()) { $city.empty().append('<option value="">---------</option>'); } // 省份选择变化时触发AJAX更新城市列表 $province.change(function() { const provinceId = $(this).val(); $city.empty().append('<option value="">加载中...</option>'); if (provinceId) { $.get('/election/get-cities/', { province_id: provinceId }, function(data) { $city.empty().append('<option value="">---------</option>'); data.forEach(city => { $city.append(`<option value="${city.id}">${city.name}</option>`); }); }).fail(function() { $city.empty().append('<option value="">加载失败,请重试</option>'); }); } else { $city.empty().append('<option value="">---------</option>'); } }); }); </script> {% endblock %}
5. 配置Election的Admin类
在election/admin.py中指定使用自定义模板:
from django.contrib import admin from .models import Province, City, Election class ElectionAdmin(admin.ModelAdmin): change_form_template = 'admin/election/election/change_form.html' fields = ('province', 'city') # 页面显示的字段 admin.site.register(Province) admin.site.register(City) admin.site.register(Election, ElectionAdmin)
方案二:用第三方库快速实现(省心省力)
如果不想手动写JS,可以用django-admin-autocomplete-light库简化实现:
1. 安装库
pip install django-admin-autocomplete-light
2. 修改settings.py
将dal和dal_admin加入INSTALLED_APPS,注意要放在django.contrib.admin前面:
INSTALLED_APPS = [ 'dal', 'dal_admin', 'django.contrib.admin', # 其他你的应用... ]
3. 配置Admin类
在election/admin.py中设置自动补全字段,并限制城市查询范围:
from django.contrib import admin from .models import Province, City, Election class CityAdmin(admin.ModelAdmin): search_fields = ['name'] # 用于自动补全搜索 class ElectionAdmin(admin.ModelAdmin): autocomplete_fields = ['province', 'city'] # 开启字段自动补全 # 编辑页面加载时,根据已选省份过滤城市选项 def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) if obj and obj.province: form.base_fields['city'].queryset = City.objects.filter(province=obj.province) return form admin.site.register(Province) admin.site.register(City, CityAdmin) admin.site.register(Election, ElectionAdmin)
该库还支持更完善的动态联动,可参考官方文档补充JS逻辑进一步优化体验。
内容的提问来源于stack exchange,提问作者raya mansouri
相关产品推荐
相关产品推荐

