【问题标题】:Convert hierarchical dictionary to HTML nested dropdown将分层字典转换为 HTML 嵌套下拉列表
【发布时间】:2023-01-12 01:48:00
【问题描述】:

我有一个这样的字典列表, 但我们可能有更多的深度,所以更多的 id 和 pids ...

WIDGETS = [
    {"id": 1, "pid": 0, "url": "/upload"},
    {"id": 2, "pid": 0, "url": "/entry"},
    {"id": 3, "pid": 0, "url": "/report"},
    {"id": 4, "pid": 3, "url": "/reppremium"},
    {"id": 5, "pid": 4, "url": "/reppremiumsum"},
    {"id": 6, "pid": 4, "url": "/reppremiumfull"},
    {"id": 7, "pid": 3, "url": "/repcommission"},
    {"id": 8, "pid": 7, "url": "/repcommissionsum"},
    {"id": 9, "pid": 7, "url": "/repcommissionfull"},
    {"id": 10, "pid": 3, "url": "/repportions"},
    {"id": 11, "pid": 10, "url": "/repportionssum"},
    {"id": 12, "pid": 10, "url": "/repportionsfull"},
    {"id": 13, "pid": 0, "url": "/adduser"},
    {"id": 14, "pid": 0, "url": "/exportdb"},
    {"id": 15, "pid": 0, "url": "/importdb"},
]

我想将其转换为 HTML 嵌套/多级下拉列表,如下所示:

main menu -> /upload
             /report -> /reppremium    ->  /reppremiumsum
                                       ->   /reppremiumfull

                     -> /repcommission ->  /repcommissionsum
                                       ->  /repcommissionfull


                     -> /repportions   ->  /repportionssum
                                       ->  /repportionsfull
             /adduser
             /exportdb
             /importdb

我已经尝试了一些代码,但它不能正常工作,因为我知道它需要一个递归函数......

def get_widgets(widgets,text='',pid=0,text_m=''):
    childs = get_childs(pid,widgets)
    for child in childs:
 
        pidn = child['id']
        n = get_childs(pidn,widgets)
        print(n,'for id',pidn)


        if len(n) != 0:
            text += f'''
            <li class="nav-item dropend">
            <a class="nav-link dropdown-toggle" href="{ child['url'] }" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                { child['url'] }
            </a>
            <ul class="dropdown-menu nav nav-pills flex-column mb-sm-auto mb-0 align-items-center align-items-sm-start">
            '''
            pid_new = child['id']
            get_widgets(widgets,text,pid_new)
            text += '</ul></li>'
            print(text)
            text_m += text
        else:
            #print(n,'n')
            text += f'''
            <li class="nav-item">
                <a class="nav-link dropdown-item" href="{ child['url'] }">{ child['url'] }</a>
            </li>
            ''' 
            text_m += text
    


        text = ''



 
    return tex

我希望代码显示一个 html 多级下拉菜单...但由 WIDGETS 填充...

【问题讨论】:

  • 你能显示你期望的输入的 HTML 输出吗?

标签: python html recursion drop-down-menu nested


【解决方案1】:

正如您所猜测的那样,这应该递归地完成,并且有几种方法可以解决它。

这是完整的代码:

WIDGETS = [
    {"id": 1, "pid": 0, "url": "/upload"},
    {"id": 2, "pid": 0, "url": "/entry"},
    {"id": 3, "pid": 0, "url": "/report"},
    {"id": 4, "pid": 3, "url": "/reppremium"},
    {"id": 5, "pid": 4, "url": "/reppremiumsum"},
    {"id": 6, "pid": 4, "url": "/reppremiumfull"},
    {"id": 7, "pid": 3, "url": "/repcommission"},
    {"id": 8, "pid": 7, "url": "/repcommissionsum"},
    {"id": 9, "pid": 7, "url": "/repcommissionfull"},
    {"id": 10, "pid": 3, "url": "/repportions"},
    {"id": 11, "pid": 10, "url": "/repportionssum"},
    {"id": 12, "pid": 10, "url": "/repportionsfull"},
    {"id": 13, "pid": 0, "url": "/adduser"},
    {"id": 14, "pid": 0, "url": "/exportdb"},
    {"id": 15, "pid": 0, "url": "/importdb"},
]


def build_HTML(d, text=""):
    for (id_, url), children_list in d.items():
        text += f"<li>{url}"

        if children_list:
            text += "<ul>"
            for dd in children_list:
                text += build_HTML(dd, "")
            text += "</ul>"

        text += "</li>"

    return text


def set_recursive(obj, d):
    for (id_, url), children_list in d.items():
        if obj["pid"] == id_:
            children_list.append({(obj["id"], obj["url"]): []})
            return

    for item in children_list:
        set_recursive(obj, item)


root = {(0, "/main-menu"): []}
while WIDGETS:
    for idx, d in enumerate(WIDGETS):
        set_recursive(d, root)
        del WIDGETS[idx]
        break

print(f"<ul>{build_HTML(root)}</ul>")

输出:

<ul><li>/main-menu<ul><li>/upload</li><li>/entry</li><li>/report<ul><li>/reppremium<ul><li>/reppremiumsum</li><li>/reppremiumfull</li></ul></li><li>/repcommission<ul><li>/repcommissionsum</li><li>/repcommissionfull</li></ul></li><li>/repportions<ul><li>/repportionssum</li><li>/repportionsfull</li></ul></li></ul></li><li>/adduser</li><li>/exportdb</li><li>/importdb</li></ul></li></ul>

解释:

set_recursive() 函数中,我们基本上创建了另一个数据结构,形式如下:

{(id, url): [<list of sub-elements>], ...}

现在这是一个元素字典,它跟踪每个子元素。它的工作方式是,对于每个元素,它递归地检查数据结构,看是否能找到它的“父母”.如果找到,则它属于该列表。在我们处理之后,我们只是将其从记录中删除。

build_HTML() 函数中,您以最压缩的形式创建字符串(浏览器的解析器不关心)。

这个函数的要点是在进入children_list之前需要先打开&lt;ul&gt;,然后关闭children_list

如果您呈现该字符串:

<!DOCTYPE html>
<html>

<head>
</head>


<body>

    <ul><li>/main-menu<ul><li>/upload</li><li>/entry</li><li>/report<ul><li>/reppremium<ul><li>/reppremiumsum</li><li>/reppremiumfull</li></ul></li><li>/repcommission<ul><li>/repcommissionsum</li><li>/repcommissionfull</li></ul></li><li>/repportions<ul><li>/repportionssum</li><li>/repportionsfull</li></ul></li></ul></li><li>/adduser</li><li>/exportdb</li><li>/importdb</li></ul></li></ul>

</body>

该字符串的美化版本是:

<ul>
    <li>/main-menu
        <ul>
            <li>/upload</li>
            <li>/entry</li>
            <li>/report<ul>
                    <li>/reppremium
                        <ul>
                            <li>/reppremiumsum</li>
                            <li>/reppremiumfull</li>
                        </ul>
                    </li>
                    <li>/repcommission
                        <ul>
                            <li>/repcommissionsum</li>
                            <li>/repcommissionfull</li>
                        </ul>
                    </li>
                    <li>/repportions
                        <ul>
                            <li>/repportionssum</li>
                            <li>/repportionsfull</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>/adduser</li>
            <li>/exportdb</li>
            <li>/importdb</li>
        </ul>
    </li>
</ul>

【讨论】:

    猜你喜欢
    • 2020-09-03
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 2022-12-05
    • 2017-07-29
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多