Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verbose mode in Django template tags

Is there any possibility to write into generated view verbose informations about template generation in debug mode? For example it could generate such output:

base.html:

<html>
<body>
{% block content %}
{% endblock %}
</body>
</html>

page.html:

{% extend "base.html" %}
{% block content %}
Foo
{% include "inner.html" %}
Bar
{% endblock %}

Into such form:

<html>
<body>
<!-- block content -->
<!-- from "page.html" -->
Foo
<!-- include "inner.html" -->
Bar
<!-- endblock content -->
</body>
</html>

Why? Because sometimes exploring some larger dependencies are very hard just by IDE. Or maybe you know some good tool for easier navigation (generating graphs etc.)? Of course this informations should be generated only in debug mode. In production they should disappear.

like image 782
zwierzak Avatar asked Apr 02 '13 20:04

zwierzak


1 Answers

You might be able to achieve this using middlware. I was having a similar issue a while back keeping track of templates and the views calling them so I wrote a middleware snippet that added a comment block to the top of the html response. It doesn't quite do what you're asking but you might be able to adapt it.

COMMENT_BLOCK = """
<!--
[ url      ] >> http://%(host)s%(path)s
[ referer  ] >> %(referer)s
[ module   ] >> %(module)s
[ function ] >> %(function)s, line %(line)s
[ args     ] >> args=%(args)s, kwargs=%(kwargs)s, defaults=%(defaults)s
[ template ] >> %(template)s
-->

"""

# Add any additional template types you wish to add the comment block to.
MIMETYPES = (
    "text/html",
    "text/xml",
)


class HtmlTemplateFinder:

    def __init__(self):
        self.host = None
        self.referer = None
        self.path = None
        self.module = None
        self.function = None
        self.line = None
        self.args = None
        self.kwargs = None
        self.defaults = None
        self.template = None
        self.valid_template = False

    def _populate_comment_block(self):
        return COMMENT_BLOCK % {
                                'host': self.host,
                                'referer': self.referer,
                                'path': self.path,
                                'module': self.module,
                                'function': self.function,
                                'line': self.line,
                                'args': self.args,
                                'kwargs': self.kwargs,
                                'defaults': self.defaults,
                                'template': self.template,
                               }

    def process_view(self, request, view_func, view_args, view_kwargs):
        self.host = request.META.get('HTTP_HOST', None)
        self.referer = request.META.get('HTTP_REFERER', None)
        self.path = request.path
        self.module = view_func.func_code.co_filename
        self.function = ('.').join((view_func.__module__, view_func.func_name))
        self.line = view_func.func_code.co_firstlineno
        self.args = view_args
        self.kwargs = view_kwargs
        self.defaults = view_func.func_defaults
        return None

    def process_template_response(self, request, response):
        from mimetypes import guess_type
        # Use this rather than response.template_name, this always returns str
        self.template = response.resolve_template(response.template_name).name
        self.valid_template = guess_type(self.template)[0] in MIMETYPES
        return response

    def process_response(self, request, response):
        from <your app> import settings
        if settings.DEBUG:
            if self.valid_template:
                block = self._populate_comment_block()
                response.content = "%s%s" % (block, response.content)
        return response
like image 89
PT114 Avatar answered Oct 09 '22 22:10

PT114