Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I validate the syntax of a django template?

Tags:

python

django

I would like client admins to be able to edit the various status emails that their site is sending. The emails are very simple django templates, stored in the database.

I would like to verify that they don't have any syntax errors, missing variables, etc., but I can't figure a simple way to do so.

For unknown block tags, it's easy:

from django import template

def render(templ, **args):
    """Convenience function to render a template with `args` as the context.
       The rendered template is normalized to 1 space between 'words'.
    """
    try:
        t = template.Template(templ)
        out_text = t.render(template.Context(args))
        normalized = ' '.join(out_text.split())
    except template.TemplateSyntaxError as e:
        normalized = str(e)
    return normalized

def test_unknown_tag():
    txt = render("""
      a {% b %} c
    """)
    assert txt == "Invalid block tag: 'b'"

I don't know how I would detect an empty variable though? I'm aware of the TEMPLATE_STRING_IF_INVALID setting, but that is a site-wide setting.

def test_missing_value():
    txt = render("""
      a {{ b }} c
    """)
    assert txt == "?"

missing closing tags/values don't cause any exceptions either..

def test_missing_close_tag():
    txt = render("""
      a {% b c
    """)
    assert txt == "?"

def test_missing_close_value():
    txt = render("""
      a {{ b c
    """)
    assert txt == "?"

Do I have to write a parser from scratch to do basic syntax validation?

like image 954
thebjorn Avatar asked Oct 21 '22 01:10

thebjorn


1 Answers

I don't know how I would detect an empty variable though?

class CheckContext(template.Context):

    allowed_vars = ['foo', 'bar', 'baz']

    def __getitem__(self, k):
        if k in self.allowed_vars:
            return 'something'
        else:
            raise SomeError('bad variable name %s' % k)

missing closing tags/values don't cause any exceptions either..

You can simply check that no {%, }} etc. are left in the rendered string.

like image 84
Vasiliy Faronov Avatar answered Oct 22 '22 17:10

Vasiliy Faronov