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

如何用django-autocomplete-light和django-hacker实现Django Admin级联下拉?

问题描述
  • 现有三个关联模型:university(大学)、Course(课程)、enquiry(咨询),关联关系为 enquiry → Course → university
  • 添加enquiry数据时,希望course_interested字段仅显示与所选university_interested关联的有效课程(即Active=True的课程)
  • 尝试过django-smart-select但未成功,不熟悉jQuery和Ajax,需要可行的实现方案

用户提供的models.py代码:

class university(models.Model):
    univ_name = models.CharField(max_length=100)
    country = CountryField(blank=True, null=True)
    univ_desc = models.CharField(max_length=1000)
    univ_logo = models.ImageField(upload_to="media")
    univ_phone = models.CharField(max_length=10, blank=True)
    univ_email = models.EmailField(max_length=254, blank=True)
    univ_website = models.URLField(blank=True)
    assigned_users = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, default="")

    def __str__(self):
        return self.univ_name

    class Meta:
        verbose_name_plural = "Universities"


class Course(models.Model):
    university = models.ForeignKey(university, on_delete=models.CASCADE)
    course_name = models.CharField(max_length=100)
    course_levels = models.ForeignKey(course_levels, on_delete=models.CASCADE)
    intake = models.ForeignKey(intake, on_delete=models.CASCADE)
    documents_required = models.ForeignKey(documents_required, on_delete=models.CASCADE)
    course_requirements = models.ForeignKey(course_requirements, on_delete=models.CASCADE)
    Active = models.BooleanField()

    def __str__(self):
        return self.course_name


class enquiry(models.Model):
    student_name = models.CharField(max_length=100)
    student_phone = models.CharField(max_length=10)
    student_email = models.EmailField()
    student_address = models.TextField()
    current_education = models.ForeignKey(current_education, on_delete=models.CASCADE)
    country_interested = CountryField(blank=True, null=True)
    university_interested = models.ForeignKey(university, on_delete=models.CASCADE)
    course_interested = models.ForeignKey(Course, on_delete=models.CASCADE, limit_choices_to={'Active':True})
    level_applying_for = models.ForeignKey(course_levels, on_delete=models.CASCADE)
    intake_interested = models.ForeignKey(intake, on_delete=models.CASCADE)
    assigned_users = models.ForeignKey(User, on_delete=models.CASCADE, default="", limit_choices_to={"is_active": True})
    enquiry_status = models.ForeignKey(enquiry_status, on_delete=models.CASCADE, default="")

    course_interested= ChainedForeignKey(Course,chained_field= 'university_interested',chained_model_field= 'university',show_all= False,auto_choose= True,sort=True,limit_choices_to = {"Active": True},)
解决方案

第一步:修复模型字段重复问题

你的enquiry模型中重复定义了course_interested字段,删除原ForeignKey定义,仅保留ChainedForeignKey:

class enquiry(models.Model):
    # 保留其他所有字段
    university_interested = models.ForeignKey(university, on_delete=models.CASCADE)
    # 移除这一行:course_interested = models.ForeignKey(Course, on_delete=models.CASCADE, limit_choices_to={'Active':True})
    # 保留链式外键定义
    course_interested= ChainedForeignKey(
        Course,
        chained_field='university_interested',
        chained_model_field='university',
        show_all=False,
        auto_choose=True,
        sort=True,
        limit_choices_to={"Active": True},
    )
    # 保留其他所有字段

第二步:正确配置django-smart-select

1. 安装依赖

确保已安装django-smart-select:

pip install django-smart-selects

2. 配置settings.py

在INSTALLED_APPS中添加应用:

INSTALLED_APPS = [
    # 其他已安装应用
    'smart_selects',
]

添加全局配置(复用Django自带的jQuery,Admin环境下无需额外引入):

USE_DJANGO_JQUERY = True

3. 配置urls.py

在项目根路由中添加smart-selects的路由:

from django.urls import path, include

urlpatterns = [
    # 其他路由
    path('smart-selects/', include('smart_selects.urls')),
]

第三步:在Admin/表单中使用

Admin环境

直接注册enquiry模型即可,Admin会自动渲染动态过滤的下拉框:

from django.contrib import admin
from .models import enquiry

admin.site.register(enquiry)

此时在Admin添加enquiry时,选择university_interested后,course_interested会自动过滤出该大学下的有效课程。

自定义表单环境

创建ModelForm后,模板中直接渲染表单即可,smart-selects会自动注入动态过滤逻辑:

from django import forms
from .models import enquiry

class EnquiryForm(forms.ModelForm):
    class Meta:
        model = enquiry
        fields = '__all__'

模板中使用{{ form.as_p }}或手动渲染字段即可。

无JS替代方案(体验稍差)

如果不想用第三方库或JS,可采用分步提交的方式:

  1. 第一步表单仅让用户选择大学,提交后跳转至第二步
  2. 第二步根据选中的大学ID,后端过滤出对应课程,渲染最终表单

示例视图代码:

from django.shortcuts import render, redirect
from .models import university, Course, enquiry
from .forms import EnquiryForm

def create_enquiry_step1(request):
    if request.method == 'POST':
        univ_id = request.POST.get('university')
        return redirect('create_enquiry_step2', univ_id=univ_id)
    universities = university.objects.all()
    return render(request, 'step1.html', {'universities': universities})

def create_enquiry_step2(request, univ_id):
    univ = university.objects.get(id=univ_id)
    courses = Course.objects.filter(university=univ, Active=True)
    if request.method == 'POST':
        form = EnquiryForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('enquiry_list')
    else:
        form = EnquiryForm(initial={'university_interested': univ_id})
        form.fields['course_interested'].queryset = courses
    return render(request, 'step2.html', {'form': form, 'univ': univ})

内容的提问来源于stack exchange,提问作者amit patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:06:05