2017-05-08 53 views
1

我有兩個型號的存儲和抽屜包含在查詢中peewee(瓶)一對多關係

class Storage(BaseModel): 
    id = PrimaryKeyField() 
    name = CharField() 
    description = CharField(null=True) 

class Drawer(BaseModel): 
    id = PrimaryKeyField() 
    name = CharField() 
    storage = ForeignKeyField(Storage, related_name="drawers") 

在我從選擇查詢

storages = Storage.select() 

生產JSON作爲一個結果,我的那一刻已經有了一個JSON數組,它看起來像這樣:

[{ 
    description: null, 
    id: 1, 
    name: "Storage" 
}, 
{ 
    description: null, 
    id: 2, 
    name: "Storage 2" 
}] 

我知道,peewee允許查詢與所有的抽屜。但是我努力將json數組包含到包含該存儲的所有抽屜的每個存儲中。我試圖使用加入

storages = Storage.select(Storage, Drawer) 
        .join(Drawer) 
        .where(Drawer.storage == Storage.id) 
        .group_by(Storage.id) 

但我只是檢索有抽屜的第二個存儲,但不包括抽屜的數組。這甚至有可能加入?或者是否需要遍歷每個存儲檢索抽屜並將它們附加到存儲?

回答

2

這是ORM的經典O(n)查詢問題。文檔goes into some detail on various ways to approach the problem

對於這種情況下,您可能需要prefetch()。而不是O(n)查詢,它將執行O(k)個查詢,每個查詢涉及一個表(在您的情況下爲2)。

storages = Storage.select().order_by(Storage.name) 
drawers = Drawer.select().order_by(Drawer.name) 
query = prefetch(storages, 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)) 
相關的抽屜會一直使用Drawer.storage外鍵的 related_name +「_prefetch」( drawers_prefetch)預填充
+0

謝謝!像魅力一樣工作,一定是錯過了文檔的這個特定部分。正在用錯誤的流行語搜索。 – stengelp