You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Admin中限制StudentGrade的student选项关联所选subject_teacher

Django Admin实现StudentGrade字段联动解决方案

1. 自定义ModelForm过滤初始学生列表

创建forms.py,重写StudentGrade的表单,根据已选的subject_teacher过滤student选项:

from django import forms
from .models import StudentGrade

class StudentGradeForm(forms.ModelForm):
    class Meta:
        model = StudentGrade
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 编辑页面时,根据已有subject_teacher过滤学生
        if self.instance.pk and self.instance.subject_teacher:
            self.fields['student'].queryset = self.instance.subject_teacher.students.all()
        else:
            # 新增页面初始状态下清空学生选项
            self.fields['student'].queryset = self.fields['student'].queryset.none()

2. 配置Admin类并引入前端联动JS

修改admin.py,使用自定义表单,并添加媒体文件引入:

from django.contrib import admin
from .models import StudentGrade
from .forms import StudentGradeForm

class StudentGradeAdmin(admin.ModelAdmin):
    form = StudentGradeForm

    class Media:
        # 替换为你的静态文件实际路径
        js = ('admin/js/student_grade联动.js',)

admin.site.register(StudentGrade, StudentGradeAdmin)

3. 编写前端联动JS

在项目静态目录(如static/admin/js/)下创建student_grade联动.js,监听subject_teacher选择变化并更新学生选项:

document.addEventListener('DOMContentLoaded', function() {
    const subjectTeacherSelect = document.getElementById('id_subject_teacher');
    const studentSelect = document.getElementById('id_student');

    subjectTeacherSelect.addEventListener('change', function() {
        const subjectTeacherId = this.value;
        if (!subjectTeacherId) {
            studentSelect.innerHTML = '<option value="">---------</option>';
            return;
        }

        // 替换URL中的your_app_name为实际应用名称
        fetch(`/admin/your_app_name/subjectteacher/${subjectTeacherId}/students/`)
            .then(response => response.json())
            .then(data => {
                studentSelect.innerHTML = '<option value="">---------</option>';
                data.forEach(student => {
                    const option = document.createElement('option');
                    option.value = student.id;
                    option.textContent = student.name;
                    studentSelect.appendChild(option);
                });
            })
            .catch(err => console.error('加载学生列表失败:', err));
    });
});

4. 添加后端接口返回学生数据

在admin.py中添加自定义视图(或单独创建admin_views.py),提供学生数据的JSON接口:

from django.http import JsonResponse
from django.contrib.admin.views.decorators import staff_member_required
from .models import SubjectTeacher

@staff_member_required
def get_subject_teacher_students(request, pk):
    subject_teacher = SubjectTeacher.objects.get(pk=pk)
    # 根据StudentProfile实际字段调整返回的名称,这里假设关联了User模型
    students = subject_teacher.students.values('id', 'user__first_name', 'user__last_name')
    student_list = [
        {'id': s['id'], 'name': f"{s['user__first_name']} {s['user__last_name']}"}
        for s in students
    ]
    return JsonResponse(student_list, safe=False)

5. 配置接口路由

在项目urls.py中添加接口路由:

from django.contrib import admin
from django.urls import path
from your_app_name.admin import get_subject_teacher_students  # 替换为实际导入路径

urlpatterns = [
    path('admin/', admin.site.urls),
    # 替换your_app_name为实际应用名称
    path('admin/your_app_name/subjectteacher/<int:pk>/students/', get_subject_teacher_students, name='get_subject_teacher_students'),
]

注意事项

  • 替换所有代码中的your_app_name为你的Django应用名称
  • 根据StudentProfile的实际字段调整视图和JS中的学生名称显示逻辑
  • 确保静态文件配置正确,JS文件能被Admin页面加载
  • 接口使用staff_member_required确保只有管理员能访问,符合权限控制

内容的提问来源于stack exchange,提问作者Dark Angel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:15:34