在Django中实现子部门基于主部门的联动选择
在Django中实现子部门基于主部门的联动选择
嘿,我明白你的问题了——你希望实现部门和子部门的联动下拉:选完主部门后,子部门的下拉列表只显示属于这个主部门的选项,而不是把所有子部门都列出来对吧?这在Django里需要结合后端API和前端JS来实现,我一步步给你说怎么做:
第一步:完善模型小细节
我看到你的SubDepartment模型的__str__方法没写完,先补上这行,方便在后台和下拉框里正常显示子部门名称:
class SubDepartment(models.Model): sub_department_name=models.CharField(max_length=100,null=False,blank=False) department_name=models.ForeignKey(Department,on_delete=models.CASCADE) company_name=models.ForeignKey(CompanyName,on_delete=models.CASCADE) status=models.CharField(max_length=20, choices=[('active','Active'),('inactive','Inactive')]) def __str__(self): return self.sub_department_name # 补上这行
另外,子部门的company_name其实可以通过关联的主部门自动获取,不用手动选择,这样能避免用户选错。这个逻辑我们可以在表单里处理,后面会提到。
第二步:添加后端API接口,根据部门ID获取子部门
我们需要写一个视图,接收前端传来的部门ID,返回对应的子部门列表,供前端动态调用。在views.py里添加:
from django.http import JsonResponse def get_sub_departments(request): # 获取前端传过来的部门ID department_id = request.GET.get('department_id') if department_id: # 过滤出属于该部门的子部门,只返回ID和名称字段 sub_depts = SubDepartment.objects.filter(department_name_id=department_id).values('id', 'sub_department_name') return JsonResponse(list(sub_depts), safe=False) # 如果没有传部门ID,返回空列表 return JsonResponse([], safe=False)
然后在你的urls.py里添加这个路由:
path('get-sub-depts/', views.get_sub_departments, name='get-sub-depts'),
第三步:优化子部门表单(可选)
如果是添加子部门的表单,其实不需要让用户手动选company_name,因为子部门的公司肯定和主部门的公司一致。你可以修改SubDepartmentForm,自动填充这个字段:
class SubDepartmentForm(forms.ModelForm): class Meta: model = SubDepartment # 去掉company_name,不让用户手动选择 fields = ['sub_department_name', 'department_name', 'status'] def save(self, commit=True): instance = super().save(commit=False) # 从选中的主部门获取公司名称,自动赋值 instance.company_name = instance.department_name.company_name if commit: instance.save() return instance
第四步:前端实现联动逻辑
假设你是在需要同时选择部门和子部门的页面(比如员工信息表单、关联表单),需要在模板里添加JS来监听部门下拉的变化,动态更新子部门选项。下面是示例代码:
<!-- 你的表单部分 --> <form method="POST"> {% csrf_token %} <div class="form-group"> <label for="id_department_name">选择主部门</label> {{ form.department_name }} <!-- 这是部门的下拉框 --> </div> <div class="form-group"> <label for="id_sub_department_name">选择子部门</label> {{ form.sub_department_name }} <!-- 这是子部门的下拉框 --> </div> <!-- 其他表单字段 --> <button type="submit">提交</button> </form> <!-- 引入jQuery(如果你的项目已经有JS库,就用你自己的) --> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script> $(document).ready(function() { // 监听主部门下拉框的变化事件 $('#id_department_name').change(function() { const departmentId = $(this).val(); // 发送AJAX请求到我们刚才写的API $.ajax({ url: "{% url 'get-sub-depts' %}", data: { 'department_id': departmentId }, dataType: 'json', success: function(subDepts) { // 清空子部门下拉框 $('#id_sub_department_name').empty(); // 添加默认提示选项 $('#id_sub_department_name').append('<option value="">请选择子部门</option>'); // 遍历返回的子部门,添加到下拉框里 $.each(subDepts, function(index, dept) { $('#id_sub_department_name').append(`<option value="${dept.id}">${dept.sub_department_name}</option>`); }); } }); }); // 如果页面加载时已经选中了主部门(比如编辑页面),自动触发一次变化事件,加载对应的子部门 const initialDeptId = $('#id_department_name').val(); if (initialDeptId) { $('#id_department_name').trigger('change'); } }); </script>
为什么你的现有代码没生效?
你现在的表单只是普通的ModelForm,默认的下拉框是后端渲染的静态内容,页面加载后就固定了。要实现动态过滤,必须用前端JS配合后端API来实时获取对应的数据,这样才能做到选完主部门后,子部门列表自动更新。
这样改完之后,当你选完主部门,子部门下拉就只会显示属于这个主部门的选项啦!
备注:内容来源于stack exchange,提问作者Anwar Ahammed
相关产品推荐
相关产品推荐

