Django Admin添加页实现按Plan选择过滤Test下拉选项(多外键模型)
在Django Admin中实现Plan选择过滤Test下拉列表
嘿,我来给你分享个超实用的简便方案,不用额外依赖第三方库,用原生Django+JavaScript就能搞定这个需求!
步骤1:自定义Result的Admin表单和配置
首先在你的admin.py里,给Result模型创建自定义表单,初始化时根据已选的Plan过滤Test选项,同时指定加载自定义JS:
from django.contrib import admin from .models import TestPlan, Test, Result from django import forms class ResultAdminForm(forms.ModelForm): class Meta: model = Result fields = '__all__' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 编辑已有Result时,根据关联的Plan过滤Test选项 if self.instance.pk and self.instance.plan: self.fields['test'].queryset = Test.objects.filter(test_plan=self.instance.plan) else: # 新建时默认清空Test选项,等选完Plan再加载 self.fields['test'].queryset = Test.objects.none() class ResultAdmin(admin.ModelAdmin): form = ResultAdminForm list_display = ('plan', 'test', 'status', 'version') # 可根据需求调整显示字段 # 引入自定义JS文件 class Media: js = ('admin/js/filter_test_by_plan.js',) # 注册所有模型 admin.site.register(TestPlan) admin.site.register(Test) admin.site.register(Result, ResultAdmin)
步骤2:创建动态过滤的JavaScript文件
在你的项目static/admin/js/目录下(如果没有就新建),创建filter_test_by_plan.js,用来监听Plan选择的变化,动态请求对应Test列表:
document.addEventListener('DOMContentLoaded', function() { // 获取Admin表单里的Plan和Test下拉框(Django默认生成的id是id_字段名) const planSelect = document.getElementById('id_plan'); const testSelect = document.getElementById('id_test'); // 监听Plan选择变化 planSelect.addEventListener('change', function() { const planId = this.value; // 如果没选Plan,清空Test选项 if (!planId) { testSelect.innerHTML = '<option value="">---------</option>'; return; } // 请求后端获取对应Plan的Test列表 fetch(`/admin/get_tests_by_plan/?plan_id=${planId}`) .then(response => response.json()) .then(tests => { // 清空现有Test选项,添加默认空选项 testSelect.innerHTML = '<option value="">---------</option>'; // 遍历返回的Test数据,添加到下拉框 tests.forEach(test => { const option = document.createElement('option'); option.value = test.id; option.textContent = test.name; testSelect.appendChild(option); }); }) .catch(err => console.error('加载Test列表失败:', err)); }); });
步骤3:添加后端接口返回Test数据
在你的views.py里,写一个视图函数,用来根据Plan ID返回对应的Test列表,同时限制只有管理员能访问:
from django.http import JsonResponse from django.contrib.admin.views.decorators import staff_member_required from .models import Test, TestPlan @staff_member_required def get_tests_by_plan(request): plan_id = request.GET.get('plan_id') if not plan_id: return JsonResponse([], safe=False) try: # 获取指定Plan的所有Test,返回id和名称 plan = TestPlan.objects.get(id=plan_id) tests = Test.objects.filter(test_plan=plan).values('id', 'test_name') # 整理成JS需要的格式 test_list = [{'id': t['id'], 'name': t['test_name']} for t in tests] return JsonResponse(test_list, safe=False) except TestPlan.DoesNotExist: return JsonResponse([], safe=False)
然后在urls.py里添加这个接口的路由:
from django.contrib import admin from django.urls import path from .views import get_tests_by_plan urlpatterns = [ path('admin/', admin.site.urls), # 添加Test列表接口 path('admin/get_tests_by_plan/', get_tests_by_plan, name='get_tests_by_plan'), ]
最后检查配置
- 确保你的
settings.py里正确配置了静态文件路径:
STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' # 可选,部署时用 STATICFILES_DIRS = [BASE_DIR / 'static'] # 如果你的静态文件放在项目根目录的static下
- 运行
python manage.py collectstatic(生产环境需要,开发环境如果DEBUG=True的话会自动加载)
这样就能实现你要的效果了:新建或编辑Result时,选完Plan之后,Test下拉框会自动只显示属于该Plan的Test选项~
内容的提问来源于stack exchange,提问作者Eran_Z
相关产品推荐
相关产品推荐

