【问题标题】:How to get single related object after filter过滤后如何获取单个相关对象
【发布时间】:2013-05-08 19:07:07
【问题描述】:

我得到了父子(1-n)模型关系:

class Parent(models.Model):
    some_fields = models.IntegerField()

class Child(models.Model):
    parent = models.ForeignKey(Parent, relatend_name='children')
    first = models.BooleanField()
    second = models.BooleanField()

现在我根据子字段过滤父母:

Parent.objects.filter(children__first=True)

这会生成以下 SQL:

SELECT app_parent.*
FROM app_parent
INNER JOIN app_child ON app_parent.id = app_child.parent_id 
WHERE app_child.first = TRUE

之后我得到了所有父字段但是我也希望相关的子字段也能获得这样的 SQL:

SELECT app_parent.*, app_child.*
FROM app_parent
INNER JOIN app_child ON app_parent.id = app_child.parent_id 
WHERE app_child.first = TRUE

并通过 Django ORM 获取它。有什么想法吗?

更新

我认为我有很好的解决方法

parents = Parent.objects.filter(children__first=True).prefetch_related('children') \
.extra(select={'child_id': '"app_child"."id"'})
for parent in parents:
    parent.child = [child for child in parent.children.all() if child == parent.child_id][0]

【问题讨论】:

  • 查看for 循环。从预取的子项列表中筛选出的第一个子项分配了子项属性。

标签: python django django-orm django-filter


【解决方案1】:

不幸的是,您必须使用fetch_related 方法并以相反的方式进行查找。

在这种情况下,它应该是这样的:

first_children = Child.objects.filter(first=True).select_related('parent')
parents = [c.parent for c in first_children]

【讨论】:

  • 我使用这个python解决方案atm(顺便说一句我认为它应该是select_related)
  • 是的...我把它与 prefetch_related 混淆了,你是对的 :)
【解决方案2】:

您可以使用prefetch_related

Parent.objects.filter(children__first=True).prefetch_related('children')

select_related

Child.objects.filter(first=True).select_related('parent')

【讨论】:

  • 我只想要一个 first=True 的孩子
  • 如果对于每个父级,有多个子级first 为真,那么您只能随机选择返回查询集中的第一行,您可以使用Parent.objects.filter(children__first=True)[0]
  • @ArturM 我添加了 select_related 信息以让一个孩子回来,但其他评论提出了一个很好的观点......
  • @Burhan Khalid 每个父母总是有一个 first 孩子,我需要让所有父母都有一个孩子。
猜你喜欢
  • 2015-12-08
  • 1970-01-01
  • 2021-05-02
  • 2010-11-04
  • 2018-04-04
  • 1970-01-01
  • 2015-10-15
  • 2010-09-20
相关资源
最近更新 更多