python - Django:如何以不可怕的方式查询子、孙等记录
问题描述
我试图在我的员工表中返回与用户有嵌套关系的用户列表/过滤器。例如,我有员工与他们的经理绑定,我希望能够查询该经理下的所有员工(这包括主要经理下的任何其他经理下的任何员工)。因此,如果用户Bob
有 2 个直接下属,Sally
并且Brian
. 并Brian
有2个直接下属,并Sally
有3个直接下属。我希望 Bob 能够看到所有 7 名员工。现在,我可以让它工作的唯一方法是通过一个可怕的序列,如下所示..我希望他们是一种更简单/更有效的方法。
manager = Employees.objects.filter(manager_id=request.user.id).values('manager')
employee_ids = list(Employees.objects.filter(manager=manager.first()['manager']).values_list('employee', flat=True))
employees = [User.objects.get(id=i).username for i in employee_ids]
grandchildren = []
for i in employees:
user_id = User.objects.get(username=i).id
child = list(Employees.objects.filter(manager=user_id).values_list('employee', flat=True))
grandchildren.append(child)
children = list(chain.from_iterable(grandchildren))
for i in children:
user_id = User.objects.get(id=i).id
child = list(Employees.objects.filter(manager=user_id).values_list('employee', flat=True))
grandchildren.append(child)
grandchildren = list(chain.from_iterable(grandchildren))
for i in grandchildren:
employees.append(User.objects.get(id=i).username)
employees = list(set(employees))
解决方案
对不起,但你的代码看起来真的很糟糕。首先,我的意思是太多的数据库查询(其中大多数都非常未优化甚至不需要)。
根据你的描述,我建议尝试这样的事情:
manager_id = request.user.id
children_ids = list(
Employees.objects.filter(manager_id=manager_id).values_list('employee', flat=True)
)
grandchildren_ids = list(
Employees.objects.filter(manager_id__in=children_ids).values_list('employee', flat=True)
)
# If you want to go deeper, do this in a loop and stop once an empty list of IDs is fetched
# (which means that there are no descendants anymore)
# Combine all IDs and finally fetch the actual users
# (do it only once, and fetch all the users in a single query, not one by one)
employees_ids = children_ids + grandchildren_ids
employees = User.objects.filter(id__in=employees_ids)
PS:这是在开玩笑user_id = User.objects.get(id=i).id
吗?:)
推荐阅读
- c++ - 是否有 ac/c++ lib 提供具有类似 stdlib 接口的内存池实现?
- java - 在集会中与所有者一起获取任务详细信息时无法应用发布明智的过滤器
- javascript - 如何以角度关注文本框交叉组件
- angular - 角材料matcard动态内部材料网格
- c++ - 为什么OpenGL给我错误:错误:0:1:'':不支持版本'330'?
- typescript - RxJS Observable 订阅,为什么不取消订阅会导致内存泄漏?
- javascript - 防止模态在点击提交时关闭
- google-admin-sdk - 用于在 G Suite 中创建用户的 API Endpoint(带有注册 URL)
- php - 如何格式化同一数组中不同级别的数组以仅获取值?
- python - 从相似数字的集群的分组列表中查找最大值