Python Namedtuple未在Flask中正确呈现

Python Namedtuple未在Flask中正确呈现,python,flask,jinja2,Python,Flask,Jinja2,我正在使用Flask/Python应用程序,并且在jinja模板中呈现namedtuple类型数据时面临问题 我正在使用版本 Python 3.6 烧瓶1.1.2 Jinja2 3.0.1 下面是我的工作示例代码: from collections import namedtuple from flask import Flask, render_template, render_template_string # .... app = Flask(__name__) Category

我正在使用Flask/Python应用程序,并且在jinja模板中呈现namedtuple类型数据时面临问题

我正在使用版本

  • Python 3.6
  • 烧瓶1.1.2
  • Jinja2 3.0.1
下面是我的工作示例代码:

from collections import namedtuple
from flask import Flask, render_template, render_template_string

# ....
app = Flask(__name__)

Category = namedtuple(
'Category',
['name', 'priority', 'menus', 'has_next_level']
)

MenuItem = namedtuple(
    'MenuItem',
    ['title', 'url', 'target', 'id', 'parent_id', 'object_type']
)

# --- Sample input value render_template()
menu_content = {
    50: {
        'AGENTS': Category(
            name='AGENTS', 
            priority=1, 
            menus=[
                MenuItem(
                    title='Agent2', 
                    url='/monitoring/dashboard/6/agent/2', 
                    target=None, 
                    id=2, 
                    parent_id=None, 
                    object_type='agent'
                    ), 
                MenuItem(
                    title='Postgres Enterprise Manager Host', 
                    url='/monitoring/dashboard/6/agent/1', 
                    target=None, 
                    id=1, 
                    parent_id=None, 
                    object_type='agent'
                )], 
            has_next_level=True
        )
    }
}

output = None
with app.app_context():
    output = render_template_string(
        '{{ menu_content|tojson|safe }}',
        menu_content=menu_content
    )

print(output)
输出,我得到:

{“50”:{“AGENTS”:[“AGENTS”,1,[[“Agent2”,“/monitoring/dashboard/6/agent/2”,null,2,null,“agent”],[“Postgres Enterprise Manager Host”,“/monitoring/dashboard/6/agent/1”,null,1,null,“agent”]],true]

预期产出:

{“50”:{“代理”:{“has_next_level”:true,“menu”:[{“id”:2,“object_type”:“代理”,“parent_id”:null,“target”:null,“title”:“Agent2”,“url”:“/monitoring/dashboard/6/agent/2”},{“id”:1,“object_type”:“代理”,“parent_id”:null,“target”:null,“title”:“Postgres Enterprise Manager主机”,“url”:“/monitoring/dashboard/6/agent/1”}


我遗漏了什么吗?

感谢您为您的问题添加了详细信息,以便我可以重现您的问题

  • 解决你的问题
  • 解释
  • 解决方案: 输出:

    {"50": 
        {"AGENTS": 
            {"name": "AGENTS", 
            "priority": 1, 
            "menus": [
                {"title": "Agent2", "url": "/monitoring/dashboard/6/agent/2", "target": null, "id": 2, "parent_id": null, "object_type": "agent"}, 
                {"title": "Postgres Enterprise Manager Host", "url": "/monitoring/dashboard/6/agent/1", "target": null, "id": 1, "parent_id": null, "object_type": "agent"}], 
            "has_next_level": true
            }
        }
    }
    
    通过调用
    json.dumps
    您将得到一个json字符串。如果您只使用
    namedtuple\u asdict
    您将得到一个
    OrderedDict

    说明: 主要问题是,
    json.jsonecoder
    (参见此处的转换表:)默认不支持要JSONify的对象

    首先,对象
    menu content
    dict
    dict
    namedtuple

    其次,这个
    namedtuple
    包含一个
    str
    、一个
    int
    、一个
    list
    和一个
    bool

    第三,
    list
    包含2个
    namedtuple
    s

    因此,我们必须找到一种方法来说明如何正确地将这种类型的结构转换为JSON

    我们可以扩展
    json.jsonecoder
    (比如docs()中的
    ComplexEncoder
    示例),或者创建一个函数来处理这个问题

    在这里,我们使用的函数将检测每个对象的类型,并对其进行转换,以获得正确的结果

    此函数的功劳归@mistermiagi所有,他在此处发布了此函数:。 我刚刚对Python3做了一些修改

    您注意到您的
    namedtuple
    s被转换为
    list
    :这是因为
    json.jsonecoder
    (参见上面的链接)使用的转换表告诉您将Python的
    list
    s和
    tuple
    转换为json数组

    namedtuple
    tuple
    的一个子类,因此您的
    namedtuple
    将转换为JSON数组

    示例:

    menu_item = MenuItem(
                        title='Agent2', 
                        url='url2', 
                        target=None, 
                        id=2, 
                        parent_id=None, 
                        object_type='agent'
                        )
    
    menu_item_json_dumps = json.dumps(menu_item)
    print(menu_item_json_dumps)
    # OUTPUT: ["Agent2", "url2", null, 2, null, "agent"]
    
    menu_item_as_dict_json_dumps = json.dumps(menu_item._asdict())
    print(menu_item_as_dict_json_dumps)
    # OUTPUT: {"title": "Agent2", "url": "url2", "target": null, "id": 2, "parent_id": null, "object_type": "agent"}
    
    您可以在@martineau-answer中找到更多信息:

    调用上述函数将在需要时调用asdict()。
    您可以调整它,以便跳过一些无值或其他任何内容。

    可能的答案:。解决方法(可能不是100%满意):您可以使用
    \u asdict
    namedtuple
    方法。这是否回答了您的问题?@Rivers我的虚拟电视中有simplejson,但我仍然得到了一个数组。
    menu_item = MenuItem(
                        title='Agent2', 
                        url='url2', 
                        target=None, 
                        id=2, 
                        parent_id=None, 
                        object_type='agent'
                        )
    
    menu_item_json_dumps = json.dumps(menu_item)
    print(menu_item_json_dumps)
    # OUTPUT: ["Agent2", "url2", null, 2, null, "agent"]
    
    menu_item_as_dict_json_dumps = json.dumps(menu_item._asdict())
    print(menu_item_as_dict_json_dumps)
    # OUTPUT: {"title": "Agent2", "url": "url2", "target": null, "id": 2, "parent_id": null, "object_type": "agent"}