Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jinja2: How to make it fail Silently like djangotemplate

Well i don't find the answer I'm sure that it's very simple, but i just don't find out how to make it work like Django when it doesn't find a variable

i tried to use Undefined and create my own undefined but it give me problems of attribute error etc.

def silently(*args, **kwargs):
    return u''

class UndefinedSilently(Undefined):
    __unicode__ = silently
    __str__ = silently
    __call__ = silently
    __getattr__ = silently

but when i try this here it fails TypeError: 'unicode' object is not callable:

{%for dir_name, links in menu_links.items()%}
like image 539
sacabuche Avatar asked May 31 '11 02:05

sacabuche


2 Answers

You are trying to go arbitrarily deep into your undefined data. menu_links is undefined, so Jinja2 creates a new instance of your UndefinedSilently class. It then calls the __getattr__ method of this object to get the items attribute. This returns a blank unicode string. Which Python then tries to call (the () of menu_links.items()). Which raises the error that unicode objects are not callables.

That is:

menu_links.items() # becomes
UndefinedSilently().items() # becomes
UndefinedSilently().u''() # from UndefinedSilently.__getattr__

If you want to be able to go deeper than one level you can create a class that returns itself for every access attempt except __str__ and __unicode__.

def silently(*args, **kwargs):
    return u''

return_new = lambda *args, **kwargs: UndefinedSilently()

class UndefinedSilently(Undefined):
    __unicode__ = silently
    __str__ = silently
    __call__ = return_new
    __getattr__ = return_new
like image 196
Sean Vieira Avatar answered Nov 15 '22 00:11

Sean Vieira


This is an old question, but it addresses a relevant issue. I revive/answer this to assist others with reference to Django 3.1/3.2/4.0:

  1. Go to your settings.py.

  2. Add in 'OPTIONS' the following:

    'undefined': jinja2.Undefined
    
  3. With this, undefined variables will not appear when rendered, i.e. be 'silent'. The full code should look something like this:

    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [
            BASE_DIR / 'templates-jinja2'
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'environment': 'config.jinja2.environment',
            'context_processors': [],
            'undefined': jinja2.DebugUndefined
    
        },
    },
    
  4. Alternatively, you can use DebugUndefined to see undefined variables, or 'StrictUndefined' to raise exceptions where undefined variables are used.

like image 39
xax Avatar answered Nov 14 '22 23:11

xax