【问题标题】:Display all jinja object attributes显示所有 jinja 对象属性
【发布时间】:2012-11-18 02:09:19
【问题描述】:

有没有办法在 jinja 模板中显示给定对象的所有属性的名称/内容/功能。这将使调试未按预期运行的模板变得更加容易。

我正在使用 hyde 框架构建一个网站,这将非常方便,因为我仍在学习 jinja 和 hyde 的复杂性。

最初,我认为使用attr 过滤器会起作用,但这似乎需要一个名称值。我希望不必指定名称即可获取对象的所有可用属性。

一些谷歌搜索显示 django 语法如下所示,但我对 django 不熟悉,因此这可能仅适用于数据库项目。长话短说,我想要一种对任何名为 obj 的对象都适用的方法

{% for field, value in obj.get_fields %}
    {{ field }} : {{ value }} </br>
{% endfor %}

最终解决方案:

@jayven 是对的,我可以创建自己的 jinja2 过滤器。不幸的是,使用 hyde (0.8.4) 的稳定版本,在 pythonpath 中设置一个过滤器并在site.yaml 文件中设置一个简单的 yaml 值并不是一件简单的事情(有一个拉取请求)。话虽如此,我能够弄清楚!所以以下是我的最终解决方案,它最终对调试任何未知属性非常有帮助。

创建特定于站点的 hyde 扩展很容易,只需使用以下目录树创建一个本地 python 包

hyde_ext
    __init__.py
    custom_filters.py

现在创建扩展:

from hyde.plugin import Plugin
from jinja2 import environmentfilter, Environment


debug_attr_fmt = '''name:  %s
type:  %r
value: %r'''

@environmentfilter
def debug_attr(env, value, verbose=False):
    '''
    A jinja2 filter that creates a <pre> block
    that lists all the attributes of a given object
    inlcuding the value of those attributes and type.

    This filter takes an optional variable "verbose",
    which prints underscore attributes if set to True.
    Verbose printing is off by default.
    '''

    begin = "<pre class='debug'>\n"
    end = "\n</pre>"

    result = ["{% filter escape %}"]
    for attr_name in dir(value):
        if not verbose and attr_name[0] == "_":
            continue
        a = getattr(value, attr_name)
        result.append(debug_attr_fmt % (attr_name, type(a), a))
    result.append("{% endfilter %} ")
    tmpl = Environment().from_string("\n\n".join(result))

    return begin + tmpl.render() + end

    #return "\n\n".join(result)

# list of custom-filters for jinja2
filters = {
        'debug_attr' : debug_attr
        }

class CustomFilterPlugin(Plugin):
    '''
    The curstom-filter plugin allows any
    filters added to the "filters" dictionary
    to be added to hyde
    '''
    def __init__(self, site):
        super(CustomFilterPlugin, self).__init__(site)

    def template_loaded(self,template):
        super(CustomFilterPlugin, self).template_loaded(template)
        self.template.env.filters.update(filters)

要让 hyde 知道扩展名,请将 hyde_ext.custom_filters.CustomFilterPlugin 添加到 site.yaml 文件的“插件”列表中。

最后,在一个文件上进行测试,你可以将它添加到一些随机页面{{resource|debug_attr}} 或以下以获得下划线属性{{resource|debug_attr(verbose=True)}}

当然,我应该补充一点,将来只要发布 hyde 1.0,这似乎会变得容易得多。特别是因为已经有一个拉取请求等待实施一个更简单的解决方案。不过,这是了解更多关于如何使用 jinja 和 hyde 的好方法!

【问题讨论】:

  • 为什么不在服务器端只使用print(dir(object))?或 print d.items() 如果您正在处理字典
  • 我说的是直接从模板而不是在 python 解释器中运行它。我还不知道在交互模式下运行hyde 的好方法(如果有人知道好的方法,请告诉我)。运行{% print dir(obj) %} 似乎不起作用,但我确实发现{{obj|pprint(True)}} 打印与对象关联的字符串值(通常只是名称)。我之前尝试过这个,似乎由于某种原因不支持dir。我做错了吗?
  • Jinja 和大多数同类一样,严重限制了模板上可用的语言结构——这可能是 dir 不起作用的原因。因此,在模板中列出属性的能力受到限制。了解您正在处理的对象类型会有所帮助。我相信,通过字典,d.items() 可以在模板上工作

标签: python jinja2 hyde


【解决方案1】:

我认为你可以自己实现一个过滤器,例如:

from jinja2 import *

def show_all_attrs(value):
    res = []
    for k in dir(value):
        res.append('%r %r\n' % (k, getattr(value, k)))
    return '\n'.join(res)

env = Environment()
env.filters['show_all_attrs'] = show_all_attrs

# using the filter
tmpl = env.from_string('''{{v|show_all_attrs}}''')
class Myobj(object):
    a = 1
    b = 2

print tmpl.render(v=Myobj())

详情另见文档:http://jinja.pocoo.org/docs/api/#custom-filters

【讨论】:

  • 非常感谢,我不得不像你说的那样创建一个 jinja 扩展,但是在 hyde 中实现它有点复杂。因此,我在上面添加了我的确切解决方案。我选择你的答案是因为没有它我不会到达那里:)
猜你喜欢
  • 1970-01-01
  • 2013-10-31
  • 2016-09-18
  • 2018-06-28
  • 2013-04-20
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
相关资源
最近更新 更多