我使用fastapi、postgresDB,我需要创建一个返回产品类别树的端点
class CategoryTree(BaseModel):
id: int
name: str
children: list[CategoryTree] | None = None
class ListCategoryTree(RootModel):
root: list[CategoryTree]
该表包含有关产品类别的信息(postgres DB)
身份证 | 名字 | 家长 |
---|---|---|
412 | 女性 | 无 |
723 | 服装 | 412 |
9421 | 泳装 | 723 |
3 | 男士 | 无 |
633 | 服装 | 3 |
111 | 商务套装 | 633 |
87 | 儿童 | 无 |
使用 sqlalchemy 我可以获得所有类别
def rec(cat, all_categories):
if cat.parent is None:
all_categories.append(CategoryTree(
id=cat.id,
name=cat.name,
children=[]
))
else:
for parent_cat in all_categories:
if parent_cat.id == cat.parent:
parent_cat.children.append(cat)
async def get_category_tree() -> ListCategoryTree:
categories = await category_pg_service.get_categories() # request to db
all_categories = []
for cat in categories:
rec(cat, all_categories)
return ListCategoryTree(root=all_categories) # pydantic model (final result)
@router.get('', response_model=ListCategoryTree)
async def category_tree() -> ListCategoryTree:
return await get_category_tree()
我设法拿到了父母和他们孩子的名单,但孩子们也有孩子。 我需要帮助
递归模式是-
async def get_category_tree(parent=None):
return [
{
'id': cat['id'],
'name': cat['name'],
'children': await get_category_tree(cat['id']), # recur
}
for cat in await get_categories(parent) # db query
]
我不知道你的数据库,但假设我们可以通过
parent
- 查询记录
data = [
{ 'id': 412, 'name': 'Women', 'parent': None },
{ 'id': 723, 'name': 'Costumes', 'parent': 412 },
{ 'id': 9421, 'name': 'Swimwear', 'parent': 723 },
{ 'id': 3, 'name': 'Men', 'parent': None },
{ 'id': 633, 'name': 'Costumes', 'parent': 3 },
{ 'id': 111, 'name': 'Business suit', 'parent': 633 },
{ 'id': 87, 'name': 'Kids', 'parent': None },
]
def get_categories(parent=None):
return mock_query(data, parent=parent)
我现在可以编写一个
mock_query
来提供可运行的演示 -
import asyncio
async def mock_query(data, **kwargs):
await asyncio.sleep(0.1) # simulate async
return list(d for d in data if all(k in d and d[k] == v for k, v in kwargs.items()))
async def main():
print(await get_category_tree()) # build tree
asyncio.run(main())
[
{'id': 412, 'name': 'Women', 'children': [
{'id': 723, 'name': 'Costumes', 'children': [
{'id': 9421, 'name': 'Swimwear', 'children': []}
]}
]},
{'id': 3, 'name': 'Men', 'children': [
{'id': 633, 'name': 'Costumes', 'children': [
{'id': 111, 'name': 'Business suit', 'children': []}
]}
]},
{'id': 87, 'name': 'Kids', 'children': []}
]
在您自己的代码中,可能看起来更像这样 -
async def get_category_tree(parent=None):
return ListCategoryTree(root=[
CategoryTree(
id=cat['id'],
name=cat['name'],
children=(await get_category_tree(cat['id'])).root,
)
for cat in await pg_service.get_categories(parent=parent)
])
@router.get('', response_model=ListCategoryTree)
async def category_tree() -> ListCategoryTree:
return await get_category_tree()