在 peewee (Flask) 的查询中包含 OneToMany 关系
Include OneToMany relationship in query in peewee (Flask)
我有储物柜和抽屉两个型号
class Storage(BaseModel):
id = PrimaryKeyField()
name = CharField()
description = CharField(null=True)
class Drawer(BaseModel):
id = PrimaryKeyField()
name = CharField()
storage = ForeignKeyField(Storage, related_name="drawers")
目前我正在从 select 查询
生成 json
storages = Storage.select()
结果我得到了一个 json 数组,它看起来像这样:
[{
description: null,
id: 1,
name: "Storage"
},
{
description: null,
id: 2,
name: "Storage 2"
}]
我知道,peewee 允许使用 storage.drawer()
查询所有抽屉。但是我正在努力将 json 数组包含到包含该存储的所有抽屉的每个存储中。我尝试使用 join
storages = Storage.select(Storage, Drawer)
.join(Drawer)
.where(Drawer.storage == Storage.id)
.group_by(Storage.id)
但我只是取回了第二个带抽屉的储物柜,但不包括抽屉阵列。这甚至可以通过连接实现吗?或者我是否需要遍历每个存储检索抽屉并将它们附加到存储?
这是 ORM 的经典 O(n) 查询问题。文档 goes into some detail on various ways to approach the problem.
对于这种情况,您可能需要 prefetch()
。它将执行 O(k) 个查询,而不是 O(n) 个查询,每个 table 个查询(在你的情况下是 2 个)。
storages = Storage.select().order_by(Storage.name)
drawers = Drawer.select().order_by(Drawer.name)
query = prefetch(storages, drawers)
为了对此进行序列化,我们将遍历 prefetch
返回的 Storage 对象。关联的抽屉将使用 Drawer.storage 外键的 related_name
+ '_prefetch' (drawers_prefetch
):
预填充
accum = []
for storage in query:
data = {'name': storage.name, 'description': storage.description}
data['drawers'] = [{'name': drawer.name}
for drawer in storage.drawers_prefetch]
accum.append(data)
要使这个更容易,您可以使用 playhouse.shortcuts.model_to_dict
助手:
accum = []
for storage in query:
accum.append(model_to_dict(storage, backrefs=True, recurse=True))
我有储物柜和抽屉两个型号
class Storage(BaseModel):
id = PrimaryKeyField()
name = CharField()
description = CharField(null=True)
class Drawer(BaseModel):
id = PrimaryKeyField()
name = CharField()
storage = ForeignKeyField(Storage, related_name="drawers")
目前我正在从 select 查询
生成 jsonstorages = Storage.select()
结果我得到了一个 json 数组,它看起来像这样:
[{
description: null,
id: 1,
name: "Storage"
},
{
description: null,
id: 2,
name: "Storage 2"
}]
我知道,peewee 允许使用 storage.drawer()
查询所有抽屉。但是我正在努力将 json 数组包含到包含该存储的所有抽屉的每个存储中。我尝试使用 join
storages = Storage.select(Storage, Drawer)
.join(Drawer)
.where(Drawer.storage == Storage.id)
.group_by(Storage.id)
但我只是取回了第二个带抽屉的储物柜,但不包括抽屉阵列。这甚至可以通过连接实现吗?或者我是否需要遍历每个存储检索抽屉并将它们附加到存储?
这是 ORM 的经典 O(n) 查询问题。文档 goes into some detail on various ways to approach the problem.
对于这种情况,您可能需要 prefetch()
。它将执行 O(k) 个查询,而不是 O(n) 个查询,每个 table 个查询(在你的情况下是 2 个)。
storages = Storage.select().order_by(Storage.name)
drawers = Drawer.select().order_by(Drawer.name)
query = prefetch(storages, drawers)
为了对此进行序列化,我们将遍历 prefetch
返回的 Storage 对象。关联的抽屉将使用 Drawer.storage 外键的 related_name
+ '_prefetch' (drawers_prefetch
):
accum = []
for storage in query:
data = {'name': storage.name, 'description': storage.description}
data['drawers'] = [{'name': drawer.name}
for drawer in storage.drawers_prefetch]
accum.append(data)
要使这个更容易,您可以使用 playhouse.shortcuts.model_to_dict
助手:
accum = []
for storage in query:
accum.append(model_to_dict(storage, backrefs=True, recurse=True))