【问题标题】:How do you debug Mako templates?您如何调试 Mako 模板?
【发布时间】:2010-09-28 06:31:34
【问题描述】:

到目前为止,当 Mako 模板编码不正确时,我发现不可能产生可用的回溯。

除了对每一行代码进行迭代之外,还有什么方法可以调试模板?

【问题讨论】:

  • 我在 Mako 中发现了这个普遍问题。也许你应该试试 Jinja2,1. 回溯进入模板代码,2. 视图和模型更好地分离,沙盒。
  • 我不太喜欢 Jinja 的积木(类似于 Mako 的 defs),因为它们在它们被称为 / 和 / 的地方被定义。 Mako 将它们解耦——它们只在它们被调用的地方被呼应。也就是说,我对 Mako 感到非常沮丧,所以我很快就会尝试 Jinja。谢谢。
  • 也许值得考虑将更复杂的逻辑从模板层移到应用程序的其他层之一。
  • @Nikhil:Jinja2 也有相当于 Mako 的 defs。它们被称为宏:jinja.pocoo.org/2/documentation/templates#macros
  • @Prairie Dogg:那么,也许这只是对 Mako 语法的缺乏经验,因为我没有将逻辑编码到模板中。 @nosklo:太完美了。谢谢!

标签: python debugging templates jinja2 mako


【解决方案1】:

Mako 实际上提供了一个VERY nice way to track down errors in a template

from mako import exceptions

try:
    template = lookup.get_template(uri)
    print template.render()
except:
    print exceptions.html_error_template().render()

【讨论】:

  • 还有 exceptions.text_error_template().render() 用于非 HTML 环境。
  • 哼,最好避免捕获所有异常。
  • 谁能告诉我如何使用这个代码?我的意思是什么是uri?以及在我的 python 脚本中放置此代码的位置
  • 似乎有必要在这个答案中添加第二个答案以获得合理的错误消息,即app.config['MAKO_TRANSLATE_EXCEPTIONS'] = False我包装了render_template函数以包含异常处理,如下所示:from flask.ext.mako import render_template as render_template_1@ 987654326@ 不能作为评论,我会把它放在答案中。
  • 至于我也在使用的pylons,不幸的是,pylons/error.py 中的handle_mako_error 不好,应该以raise 结尾而不是raise (exc, None, sys.exc_info()[2])。可以复制该功能并为应用程序修复它。
【解决方案2】:

查看Flask-Mako 源,我发现了一个名为MAKO_TRANSLATE_EXCEPTIONS 的未记录配置参数。

在您的 Flask 应用程序配置中将此设置为 False,您会从模板中得到很好的异常。这完成了与@Mariano 建议的相同的事情,而无需编辑源代码。显然,这个参数是在马里亚诺回答之后添加的。

【讨论】:

    【解决方案3】:

    我将它们分解成碎片,然后在发现问题后重新组装。

    不好,但很难判断一个大而复杂的模板出了什么问题。

    【讨论】:

      【解决方案4】:

      我对 Mako 的主要不满是很难看到模板中发生了什么。由于模板代码是内存中的可运行对象,因此没有调试器可以查看它。

      一种解决方案是将模板代码写入文件,并使用此文件作为标准 python 模块重新运行模板。然后您就可以根据自己的喜好进行调试了。

      一个例子:

      import sys
      from mako import exceptions, template 
      from mako.template import DefTemplate
      from mako.runtime import _render
      
      <Do Great Stuff>
      
      try:
          template.render(**arguments))
      except:
          # Try to re-create the error using a proper file template
          # This will give a clearer error message.
          with open('failed_template.py', 'w') as out:
              out.write(template._code)
          import failed_template
          data = dict(callable=failed_template.render_body, **arguments)
          try:
              _render(DefTemplate(template, failed_template.render_body),
                      failed_template.render_body,
                      [],
                      data)
          except:
              msg = '<An error occurred when rendering template for %s>\n'%arguments
              msg += exceptions.text_error_template().render()
              print(msg, file=sys.stderr)
              raise
      

      【讨论】:

      • 非常方便 :) 我只需要添加一些导入:import sys from mako import exceptions, template from mako.template import DefTemplate from mako.runtime import _render
      • 好的,忘记添加导入了。我会编辑答案,谢谢。
      【解决方案5】:

      使用 flask_mako,我发现跳过 TemplateError 生成并传递异常更容易。 IE。在 flask_mako.py 中,将导致 TemplateError 的部分注释掉,然后加注:

      def _render(template, context, app):
       """Renders the template and fires the signal"""
      app.update_template_context(context)
      try:
          rv = template.render(**context)
          template_rendered.send(app, template=template, context=context)
          return rv
      except:
          #translated = TemplateError(template)                                                                                                                 
          #raise translated                                                                                                                                     
          raise
      

      }

      然后您会看到导致问题的常规 python 异常以及模板中的行号。

      【讨论】:

      • 看起来现在您可以通过烧瓶配置选项启用行为:MAKO_TRANSLATE_EXCEPTIONS = False
      【解决方案6】:

      将两个最佳答案与我自己的特殊调味料结合起来:

      from flask.ext.mako import render_template as render_template_1
      from mako import exceptions
      
      app.config['MAKO_TRANSLATE_EXCEPTIONS'] = False    # seems to be necessary
      
      def render_template(*args, **kwargs):
          kwargs2 = dict(**kwargs)
          kwargs2['config'] = app.config     # this is irrelevant, but useful
          try:
              return render_template_1(*args, **kwargs2)
          except:
              if app.config.get('DEBUG'):
                  return exceptions.html_error_template().render()
              raise
      

      它包装了股票“render_template”函数:

      • 捕获异常,并且
        • 如果调试,则呈现回溯
        • 如果不调试,请再次引发异常以便记录
      • 使配置可从页面访问(无关)

      【讨论】:

        猜你喜欢
        • 2013-03-28
        • 1970-01-01
        • 1970-01-01
        • 2011-06-23
        • 2023-02-09
        • 2014-06-27
        • 2011-07-17
        • 2019-12-13
        • 2011-01-22
        相关资源
        最近更新 更多