python – Jinja2模板编译信息
发布时间:2020-12-20 13:47:32 所属栏目:Python 来源:网络整理
导读:在 mako template engine有一个方便的 ModuleInfo class: class ModuleInfo(object): """Stores information about a module currently loaded into memory,provides reverse lookups of template source,module source code based on a module's identifie
在
mako template engine有一个方便的
ModuleInfo class:
class ModuleInfo(object): """Stores information about a module currently loaded into memory,provides reverse lookups of template source,module source code based on a module's identifier. """ 基本上,它提供了模板源代码映射,可以帮助测量模板覆盖率,请参阅coverage-mako-plugin. Jinja2最接近ModuleInfo的替代方案是什么? 仅供参考:github issue reference. 我问的原因是我正在研究“coverage-jinja2-plugin”,这基本上是一个起点. 解决方法
Jinja2在节点本身中提供了所有这些信息,每个节点都知道它所在的行号,它所在的文件以及更多.我写了一篇关于在Django中调试Jinja2的博客文章,它显示了一些例子:
http://w.wol.ph/2013/07/28/mixing-django-with-jinja2-without-losing-template-debugging/
我用来获取包含文件和代码的完整堆栈跟踪的代码: def _generate_django_exception(e,source=None): '''Generate a Django exception from a Jinja source''' from django.views.debug import linebreak_iter if source: exception = DjangoTemplateSyntaxError(e.message) exception_dict = e.__dict__ del exception_dict['source'] '''Fetch the entire template in a string''' template_string = source[0].reload() '''Get the line number from the error message,if available''' match = re.match('.* at (d+)$',e.message) start_index = 0 stop_index = 0 if match: '''Convert the position found in the stacktrace to a position the Django template debug system can use''' position = int(match.group(1)) + source[1][0] + 1 for index in linebreak_iter(template_string): if index >= position: stop_index = min(index,position + 3) start_index = min(index,position - 2) break start_index = index else: '''So there wasn't a matching error message,in that case we simply have to highlight the entire line instead of the specific words''' ignore_lines = 0 for i,index in enumerate(linebreak_iter(template_string)): if source[1][0] > index: ignore_lines += 1 if i - ignore_lines == e.lineno: stop_index = index break start_index = index '''Convert the positions to a source that is compatible with the Django template debugger''' source = source[0],( start_index,stop_index,) else: '''No source available so we let Django fetch it for us''' lineno = e.lineno - 1 template_string,source = django_loader.find_template_source(e.name) exception = DjangoTemplateSyntaxError(e.message) '''Find the positions by the line number given in the exception''' start_index = 0 for i in range(lineno): start_index = template_string.index('n',start_index + 1) source = source,( start_index + 1,template_string.index('n',start_index + 1) + 1,) exception.source = source return exception 实际的模板标签: class Template(_Jinja2Template): """Fixes the incompabilites between Jinja2's template class and Django's. The end result should be a class that renders Jinja2 templates but is compatible with the interface specfied by Django. This includes flattening a ``Context`` instance passed to render and making sure that this class will automatically use the global coffin environment. """ def __new__(cls,template_string,origin=None,name=None,source=None): # We accept the "origin" and "name" arguments,but discard them # right away - Jinja's Template class (apparently) stores no # equivalent information. from coffin.common import env try: return env.from_string(template_string,template_class=cls) except JinjaTemplateSyntaxError,e: raise _generate_django_exception(e,source) def __iter__(self): # TODO: Django allows iterating over the templates nodes. Should # be parse ourself and iterate over the AST? raise NotImplementedError() def render(self,context=None): """Differs from Django's own render() slightly in that makes the ``context`` parameter optional. We try to strike a middle ground here between implementing Django's interface while still supporting Jinja's own call syntax as well. """ if not context: context = {} else: context = dict_from_django_context(context) try: return super(Template,self).render(context) except JinjaTemplateSyntaxError,e: raise _generate_django_exception(e) def dict_from_django_context(context): """Flattens a Django :class:`django.template.context.Context` object. """ if isinstance(context,DjangoContext): dict_ = {} # Newest dicts are up front,so update from oldest to newest. for subcontext in reversed(list(context)): dict_.update(dict_from_django_context(subcontext)) return dict_ else: return context (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |