【发布时间】:2020-08-26 09:23:01
【问题描述】:
我有一个表 Parent 和一个表 Child,它有一个表 Parent 的外键。
我想查询所有有一个孩子叫 Eric 的父母,并报告 Eric 的年龄。
我跑:
parents = Parents.objects.filter(child__name='Eric')
然后我遍历查询集:
for parent in parents:
print(f'Parent name {parent.name} child Eric age {parent.child.age}')
显然这不起作用 - 我需要通过外键对象管理器访问 child,所以我尝试:
for parent in parents:
print(f'Parent name {parent.name}')
for child in parent.child_set.all():
print(f'Child Eric age {parent.child.age}')
Django 返回所有孩子的年龄,而不仅仅是名为 Eric 的孩子。
我可以重复过滤条件:
parents = Parents.objects.filter(child__name='Eric')
for parent in parents:
print(f'Parent name {parent.name}')
for child in parent.child_set.filter(name='Eric'):
print(f'Child Eric age {child.age}')
但这意味着重复的代码(因此当另一个开发人员对一个而不是另一个进行更改时,未来可能会出现不一致),并在数据库上运行第二个查询。
有没有办法获取匹配的记录并对其进行迭代?多年来一直在 Djangoing,不敢相信我不能这样做!
PS。我知道我可以做到Child.objects.filter(name='Eric').select_related('parent')。但我真正想做的涉及第二个子表。因此,在上面的示例中添加一个带有外键的表地址到父级。我想让有孩子的父母叫 Eric,地址在 Timbuktu,并遍历所有 Timbuktu 地址和所有小 Eric。这就是我不想使用 Child 的对象管理器的原因。
这是我能想到的最好的方法 - 三个查询,重复每个过滤器。
children = Children.objects.filter(name='Eric')
addresses = Address.objects.filter(town='Timbuktu')
parents=(
Parent.objects
.filter(child__name='Eric', address__town='Timbuktu')
.prefetch_related(Prefetch('child_set', children))
.prefetch_related(Prefetch('address_set', addresses))
)
【问题讨论】:
-
你想遍历没有匹配孩子的父母吗?
-
您只想遍历
Child表吗?您的Address示例可以通过子查询Child.objects.filter(name='Eric', parent__in=Parent.objects.filter(address__country='Timbuktu')).select_related('parent')解决 -
是否有特殊原因需要单个查询?你可以使用
prefetch_related并且只执行 2 -
你想避免重复代码吗? 3 次查询似乎并不过分
-
公平地说,我认为您可以使用
values()查询集在 1 个查询中获取您需要的所有数据。唯一的问题是你会有重复的数据,你去重复和迭代的逻辑会有点混乱,尽管重复的查询解决方案不是“干净的”
标签: django django-queryset django-orm