基于Django第一个模型类选择,展示第二个关联模型类字段列表的需求
实现Django中基于选择动态展示关联模型字段
咱们先把整个流程拆解清楚,从模型关联到前后端交互一步步来解决你的需求:
1. 完善模型关联定义
首先得确保两个模型的外键关联正确,这样才能通过Servico找到对应的ItemServico:
from django.db import models class Servico(models.Model): desc_servico = models.CharField('Descrição', max_length=50, default='', blank=False) def __str__(self): return self.desc_servico # 方便在表单里显示服务名称 class ItemServico(models.Model): desc_itemservico = models.CharField('Item Descrição', max_length=50, default='', blank=False) servico = models.ForeignKey(Servico, on_delete=models.CASCADE, related_name='itens') def __str__(self): return self.desc_itemservico
这里给外键加了related_name='itens',后续可以直接通过Servico实例.itens快速获取关联的子项。
2. 编写处理AJAX请求的视图
需要一个视图来接收前端传来的服务ID,返回对应的子项列表:
from django.http import JsonResponse from .models import ItemServico def get_itens_servico(request): servico_id = request.GET.get('servico_id') # 过滤出对应服务的子项,只返回需要的字段 itens = ItemServico.objects.filter(servico_id=servico_id).values('id', 'desc_itemservico') return JsonResponse(list(itens), safe=False)
3. 配置路由映射
在app的urls.py中添加这个视图的路由:
from django.urls import path from . import views urlpatterns = [ # 其他已有的路由... path('get-itens/', views.get_itens_servico, name='get_itens_servico'), ]
4. 前端实现动态更新逻辑
在模板里写表单和JavaScript,实现选择服务后自动加载对应的子项:
<form> <div class="form-group"> <label for="servico">Serviço:</label> <select id="servico" name="servico" class="form-control"> <option value="">Selecione um serviço</option> {% for servico in servicos %} <option value="{{ servico.id }}">{{ servico.desc_servico }}</option> {% endfor %} </select> </div> <div class="form-group mt-3"> <label for="item_servico">Item do Serviço:</label> <select id="item_servico" name="item_servico" class="form-control"> <option value="">Primeiro selecione um serviço</option> </select> </div> </form> <script> // 监听服务选择框的变化事件 document.getElementById('servico').addEventListener('change', function() { const servicoId = this.value; const itemSelect = document.getElementById('item_servico'); // 清空现有选项并显示加载状态 itemSelect.innerHTML = '<option value="">Carregando...</option>'; if (!servicoId) { itemSelect.innerHTML = '<option value="">Primeiro selecione um serviço</option>'; return; } // 发送AJAX请求获取子项数据 fetch(`{% url 'get_itens_servico' %}?servico_id=${servicoId}`) .then(response => response.json()) .then(data => { // 重置选项并添加新的子项 itemSelect.innerHTML = '<option value="">Selecione um item</option>'; data.forEach(item => { const option = document.createElement('option'); option.value = item.id; option.textContent = item.desc_itemservico; itemSelect.appendChild(option); }); }) .catch(error => { console.error('Erro ao carregar itens:', error); itemSelect.innerHTML = '<option value="">Erro ao carregar itens</option>'; }); }); </script>
另外,渲染这个模板的视图需要把所有Servico实例传进去:
from django.shortcuts import render from .models import Servico def form_view(request): servicos = Servico.objects.all() return render(request, 'your_template.html', {'servicos': servicos})
5. 可选:后端表单验证(用Django Form类)
如果需要后端验证,可以定义表单类,确保提交时子项和服务匹配:
from django import forms from .models import Servico, ItemServico class ServicoItemForm(forms.Form): servico = forms.ModelChoiceField(queryset=Servico.objects.all(), label='Serviço') item_servico = forms.ModelChoiceField(queryset=ItemServico.objects.none(), label='Item do Serviço') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 如果是POST请求,根据选中的服务更新子项查询集 if 'servico' in self.data: try: servico_id = int(self.data.get('servico')) self.fields['item_servico'].queryset = ItemServico.objects.filter(servico_id=servico_id) except (ValueError, TypeError): pass # 如果是编辑已有数据,初始化子项查询集 elif self.instance.pk: self.fields['item_servico'].queryset = self.instance.servico.itens.all()
这样一套下来,就能实现选择Servico后动态展示对应ItemServico的需求啦~
内容的提问来源于stack exchange,提问作者Patricia
相关产品推荐
相关产品推荐

