如何在Django Admin中根据资助方选择限制方案下拉选项?
实现方案:Project Admin表单中按选中资助方过滤方案选项
完全可以实现这个需求,核心是通过后端QuerySet过滤对应资助方的方案,结合前端JavaScript监听资助方选择事件,动态更新方案下拉框的可选范围。以下是具体实现步骤:
1. 修正Model中的错误
首先修复你的Model代码里的两处问题:
# models.py class Funder(models.Model): name = models.CharField(max_length=200) scheme = models.ManyToManyField('Scheme', blank=True) class Scheme(models.Model): name = models.CharField(max_length=200) # 移除多余的右括号 class Project(models.Model): title = models.CharField(max_length=200) funder = models.ForeignKey(Funder, on_delete=models.CASCADE) # 必须指定on_delete scheme = models.ForeignKey(Scheme, on_delete=models.SET_NULL, null=True) # SET_NULL需要配合null=True
2. 编写AJAX接口返回过滤后的方案列表
创建一个视图,根据传入的资助方ID返回其关联的方案:
# views.py from django.contrib.auth.mixins import LoginRequiredMixin from django.http import JsonResponse from django.views.generic import View from .models import Funder class SchemeAutocompleteView(LoginRequiredMixin, View): def get(self, request, *args, **kwargs): funder_id = request.GET.get('funder_id') schemes = [] if funder_id: try: funder = Funder.objects.get(id=funder_id) # 用QuerySet过滤当前资助方关联的方案 schemes = funder.scheme.all().values('id', 'name') except Funder.DoesNotExist: pass return JsonResponse(list(schemes), safe=False)
在urls.py中配置该接口的路由:
# urls.py from django.urls import path from .views import SchemeAutocompleteView urlpatterns = [ # 其他路由... path('scheme-autocomplete/', SchemeAutocompleteView.as_view(), name='scheme-autocomplete'), ]
3. 自定义Project Admin表单与逻辑
修改admin.py,自定义Project的Admin表单和ModelAdmin,引入前端JS实现动态更新:
# admin.py from django.contrib import admin from import_export.admin import ImportExportModelAdmin from django import forms from django.urls import reverse from .models import Funder, Scheme, Project class ProjectForm(forms.ModelForm): class Meta: model = Project fields = '__all__' widgets = { 'scheme': forms.Select(attrs={'id': 'id_scheme'}), 'funder': forms.Select(attrs={'id': 'id_funder'}), } class ProjectAdmin(admin.ModelAdmin): form = ProjectForm list_display = ('title', 'funder', 'scheme') def changeform_view(self, request, object_id=None, form_url='', extra_context=None): extra_context = extra_context or {} # 传递AJAX接口URL到模板 extra_context['scheme_autocomplete_url'] = reverse('scheme-autocomplete') return super().changeform_view(request, object_id, form_url, extra_context) # 引入自定义JS文件 class Media: js = ('admin/js/project_scheme_filter.js',) # 注册现有Admin class FunderAdmin(ImportExportModelAdmin): search_fields = ['name',] autocomplete_fields = ['scheme'] list_display = ("name",) admin.site.register(Funder, FunderAdmin) admin.site.register(Scheme) admin.site.register(Project, ProjectAdmin)
4. 编写前端JS实现动态过滤
在项目的静态文件目录下创建admin/js/project_scheme_filter.js,监听资助方选择事件并更新方案下拉框:
document.addEventListener('DOMContentLoaded', function() { const funderSelect = document.getElementById('id_funder'); const schemeSelect = document.getElementById('id_scheme'); // 从模板获取AJAX接口URL const autocompleteUrl = "{{ scheme_autocomplete_url }}"; // 根据资助方ID更新方案选项 function updateSchemes(funderId) { fetch(`${autocompleteUrl}?funder_id=${funderId}`) .then(response => response.json()) .then(data => { // 清空现有选项 schemeSelect.innerHTML = '<option value="">---------</option>'; // 添加过滤后的方案选项 data.forEach(scheme => { const option = document.createElement('option'); option.value = scheme.id; option.textContent = scheme.name; schemeSelect.appendChild(option); }); }); } // 监听资助方选择变化 funderSelect.addEventListener('change', function() { updateSchemes(this.value); }); // 编辑页面初始化时,加载当前资助方的方案 if (funderSelect.value) { updateSchemes(funderSelect.value); } });
5. 自定义Admin模板传递URL变量
在项目的templates目录下创建admin/[你的app名]/project/change_form.html,继承默认Admin模板并传递URL变量:
{% extends "admin/change_form.html" %} {% block extrahead %} {{ block.super }} <script> // 将模板变量转换为JS变量 const scheme_autocomplete_url = "{{ scheme_autocomplete_url }}"; </script> {% endblock %}
核心逻辑说明
- 后端通过
funder.scheme.all()这个QuerySet精准过滤出当前资助方关联的所有方案,完全符合你的需求。 - 前端通过监听资助方选择框的
change事件,实时发送AJAX请求获取过滤后的方案列表,动态更新下拉选项。 - 编辑页面初始化时会自动加载当前项目关联资助方的方案,保持数据一致性。
内容的提问来源于stack exchange,提问作者HBMCS
相关产品推荐
相关产品推荐

