Django Admin中如何根据选中的Department动态过滤Student关联的Branch选项
Django Admin 实现部门-分支联动下拉方案
两种实现方案可按需选择:
方案1:原生实时联动(无需第三方依赖,交互体验好)
第一步:自定义Student表单过滤初始分支选项
在admin.py中新增表单逻辑:
import uuid from django import forms from django.contrib import admin from django.http import JsonResponse from django.urls import path from .models import Department, Branch, Student class StudentForm(forms.ModelForm): class Meta: model = Student fields = "__all__" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 编辑已有学生时,仅加载对应部门的分支 if self.instance.pk and self.instance.department: self.fields['branch'].queryset = Branch.objects.filter(dep=self.instance.department) # 新增学生时默认分支选项为空 else: self.fields['branch'].queryset = Branch.objects.none()
第二步:新增联动JS脚本
在项目static目录下新建admin/student_form.js,内容如下:
django.jQuery(document).ready(function($) { const deptSelect = $('#id_department'); const branchSelect = $('#id_branch'); function loadRelatedBranches() { const deptId = deptSelect.val(); branchSelect.empty(); if (!deptId) return; // 请求对应部门的分支列表 $.get(`/admin/student/get-branches/?dept_id=${deptId}`, function(data) { data.forEach(item => { branchSelect.append(new Option(item.name, item.id)); }); }); } // 页面加载时如果已有选中部门自动加载分支 if (deptSelect.val()) loadRelatedBranches(); // 部门变更时刷新分支选项 deptSelect.on('change', loadRelatedBranches); });
注意需要确保你的Django项目配置了正确的静态文件访问规则,自定义JS文件放在对应static目录下才能正常加载
第三步:注册StudentAdmin并添加分支查询接口
继续在admin.py中添加如下代码:
@admin.register(Student) class StudentAdmin(admin.ModelAdmin): form = StudentForm # 注入自定义联动JS class Media: js = ('admin/student_form.js',) # 注册分支查询接口 def get_urls(self): urls = super().get_urls() custom_urls = [ path('get-branches/', self.admin_site.admin_view(self.get_branch_list), name='student-get-branches'), ] return custom_urls + urls def get_branch_list(self, request): dept_id = request.GET.get('dept_id') if not dept_id: return JsonResponse([], safe=False) branches = Branch.objects.filter(dep_id=dept_id).values('id', 'name') return JsonResponse(list(branches), safe=False) # 其他模型注册保持原有逻辑即可 admin.site.register(Department) admin.site.register(Branch)
方案2:轻量实现(无JS,仅编辑时过滤)
如果不需要实时联动,只需要编辑已有学生时显示对应分支,可直接重写formfield_for_foreignkey方法,代码更简单:
@admin.register(Student) class StudentAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == 'branch': object_id = request.resolver_match.kwargs.get('object_id') if object_id: student = Student.objects.get(pk=object_id) kwargs['queryset'] = Branch.objects.filter(dep=student.department) else: kwargs['queryset'] = Branch.objects.none() return super().formfield_for_foreignkey(db_field, request, **kwargs)
该方案缺点是新增学生时选完部门需要先保存一次,再次编辑时才会显示对应分支选项,适合对交互要求不高的场景。
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

