如何制作产品类别树?

问题描述 投票:0回答:1

我使用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()

我设法拿到了父母和他们孩子的名单,但孩子们也有孩子。 我需要帮助

python-3.x postgresql recursion tree fastapi
1个回答
0
投票

递归模式是-

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()
© www.soinside.com 2019 - 2024. All rights reserved.