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

Django技术问题:如何获取多对多字段中已选选项的列表?

解决Django中无法获取已选员工列表的AttributeError问题

问题场景

登录的管理员(Gestor)选择员工(Funcionarios)后,需要查看已选员工的列表,但在尝试获取数据时报错。

现有代码

models.py

class Equipe(models.Model):
    gestor = models.ForeignKey(Gestor, on_delete=models.PROTECT, default="")
    funcionario = models.ManyToManyField(User)
    def __str__(self):
        return self.nome
    
    def get_funcionario(self):
        return "\n".join([p.funcionario for p in self.funcionario.all()])

views.py

def listaFuncionario(request):
    gest = Gestor.objects.get(user_id = request.user.id)
    equipe = Equipe.objects.filter(gestor_id = gest)
    equipes = gest.equipe_set.all()
    func = equipes.funcionario.all()
    context = {'func':func}
    return render(request, 'listaFunc.html', context)

报错信息

func = equipes.funcionario.all()
AttributeError: 'QuerySet' object has no attribute 'funcionario'
[02/Nov/2022 15:15:06] "GET /funcionarios HTTP/1.1" 500 65882

错误原因

gest.equipe_set.all()返回的是QuerySet对象(即当前管理员关联的所有Equipe实例的集合),而funcionario是单个Equipe模型的多对多字段,只能在单个Equipe实例上调用,不能直接在QuerySet集合上访问这个属性,因此触发AttributeError。

解决方案

提供两种常用修正方式,可根据需求选择:

方式1:遍历收集所有关联员工并去重

遍历管理员的所有Equipe,收集每个Equipe下的员工,最后去重避免重复数据:

def listaFuncionario(request):
    gest = Gestor.objects.get(user_id=request.user.id)
    # 预加载关联数据,减少数据库查询次数
    equipes = gest.equipe_set.prefetch_related('funcionario').all()
    
    func_set = set()
    for equipe in equipes:
        func_set.update(equipe.funcionario.all())
    
    context = {'func': func_set}
    return render(request, 'listaFunc.html', context)

方式2:直接跨表查询获取所有关联员工

利用Django的反向关联特性,直接查询当前管理员所有Equipe关联的User对象:

def listaFuncionario(request):
    gest = Gestor.objects.get(user_id=request.user.id)
    # 跨表查询并去重,避免同一员工重复出现
    func = User.objects.filter(equipe__gestor=gest).distinct()
    
    context = {'func': func}
    return render(request, 'listaFunc.html', context)

额外优化说明

  • 两种方式中的去重操作(set()或distinct())用于避免同一员工被多个Equipe关联时出现重复数据。
  • 方式1中使用prefetch_related('funcionario')可减少数据库查询次数,避免N+1查询问题,提升性能。
  • 原models中的get_funcionario方法存在错误:p.funcionario应改为p.username或p.get_full_name()(因为p是User实例,无funcionario属性),修正后代码:
def get_funcionario(self):
    return "\n".join([p.username for p in self.funcionario.all()])

内容的提问来源于stack exchange,提问作者Gabriel Batista dos Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:50:29