[英]Peewee returns multiple Objects during an Inner Join
class Parent(BaseModel):
name = peewee.CharField()
class Child(BaseModel):
name = peewee.CharField()
parent = peewee.ForeignKeyField(Parent, related_name='children')
parent = Parent.create(name="Parent1")
child1 = Child.create(name="Child1", parent=parent)
chilld2 = Child.create(name="Child2", parent=parent)
query = (Parent.select()
.join(Child))
for p in query:
print p.name
for c in p.children:
print "\t",c.name
结果为以下输出:
Parent1
Child1
Child2
Parent1
Child1
Child2
我被期望这样:
Parent1
Child1
Child2
似乎我正在遍历一个SQL结果集,而不是ORM意义上的一个对象。 从ORM角度来看,假设查询中只有一个“父对象”,如何修改查询或对该查询的迭代以获得预期结果?
我想像在peewee示例应用程序中一样将查询返回到我的模板,并对其进行迭代以显示对象,但是如果这样做,它将显示同一对象两次(对于n个相关子对象,则显示n次)。
我知道我可以执行以下操作:
p = query.get()
print p.name
for c in p.children:
print "\t", c.name
但是,当我有多个父母并且只想遍历所有父母时,我无法确定有多少父母。 查询的count
方法返回结果集的计数,而不是结果集的计数。
这也可以解决:
pars = []
for p in query:
if p not in pars:
pars.append(p)
for p in pars:
print p.name
for c in p.children:
print "\t", c.name
您的代码有两个问题。
首先是,即使您已加入Child
,调用parent.children
也会执行一个额外的单独查询。
由于第一个问题,您误解了外部循环的作用,这只是给您Parent1 + Child1的Parent部分,Parent1 + Child2。
要解决此问题,您可以使用prefetch
或aggregate_rows
:
# Execute a single query and de-dupe the duplicated parent rows.
query = Parent.select(Parent, Child).join(Child).aggregate_rows()
for parent in query:
print parent.name
for child in parent.children:
print childname
# Execute a query for each joined table. Generally more efficient
# than aggregate_rows().
query = prefetch(Parent.select(), Child)
for parent in query:
print parent.name
for child in parent.children_prefetch: # NOTE the `_prefetch`
print child.name
对此进行了广泛的记录: http : //docs.peewee-orm.com/en/latest/peewee/querying.html#avoiding-n-1-queries
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.