probably at the beach
probably at the beach

Reputation: 15217

Jinja2 ignore UndefinedErrors for objects that aren't found

I switched to Jinja from Django but a lot of my templates broke when referencing

 {{ entity.property }}

if entity is not defined. Is there away to ignore the UndefinedErrors in certain situations, Otherwise I'll have to add in a lot of

 {% if entity %}{{ entity.property }}{% endif %}

wrappers.

Thanks, Richard

Upvotes: 23

Views: 15788

Answers (6)

Chris Cogdon
Chris Cogdon

Reputation: 8005

If you're using Jinja2 within ansible, there's a setting that lets you specify the default behaviour for a missing variable. In ansible.cfg:

[Defaults]
error_on_undefined_vars=False

Note that this, and the defaults filter, only works if what's missing is at the end of a dot path. Eg: {{ a.b.c }} will work if 'c' is missing, but will still fail with a KeyError if 'b' is missing.

Upvotes: 0

Basalex
Basalex

Reputation: 1187

Also was looking for a solution and used @s29 SilentUndefined class, but I`ve caught "'str' object is not callable" error when undefined variable was tried to be called, so this is my workaround, it could be helpful for someone

class SilentUndefined(Undefined):

    def _fail_with_undefined_error(self, *args, **kwargs):
        class EmptyString(str):
            def __call__(self, *args, **kwargs):
                return ''
        return EmptyString()

 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
    __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
    __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
    __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
    __float__ = __complex__ = __pow__ = __rpow__ = \
    _fail_with_undefined_error

Upvotes: 2

s29
s29

Reputation: 2057

I also needed to reset the class's magic methods to make object attributes etc work correctly. Adding to @rattray --

from jinja2 import Undefined, Template

class SilentUndefined(Undefined):
    def _fail_with_undefined_error(self, *args, **kwargs):
        return ''

    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
        __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
        __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
        __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
        __float__ = __complex__ = __pow__ = __rpow__ = \
        _fail_with_undefined_error        

It'd make sense to be a jinja setting. A lot of people would be coming from django templates which are silent by default.

Upvotes: 6

Al Conrad
Al Conrad

Reputation: 1618

I built on @rattray's answer above:

from jinja2 import Undefined, Template

class SilentUndefined(Undefined):
    def _fail_with_undefined_error(self, *args, **kwargs):
        return ''

Then used it with template string:

person_dict = {'first_name': 'Frank', 'last_name': 'Hervert'}
t2 = Template("{{ person1.last_name }}, {{ person.last_name }}", undefined=SilentUndefined)

print t2.render({'person': person_dict})                                                                         
# ', Hervert'

I needed to ignore the errors when rendering a Template from string directly instead of using Environment.

Upvotes: 7

rattray
rattray

Reputation: 6069

Building off of Sean's excellent and helpful answer, I did the following:

from jinja2 import Undefined
import logging

class SilentUndefined(Undefined):
    '''
    Dont break pageloads because vars arent there!
    '''
    def _fail_with_undefined_error(self, *args, **kwargs):
        logging.exception('JINJA2: something was undefined!')
        return None

and then env = Environment(undefined=SilentUndefined) where I was calling that.

In the django_jinja library, which I use, the above is in base.py and is actually a modification of initial_params

Upvotes: 9

Sean Vieira
Sean Vieira

Reputation: 160033

Jinja2 actually uses a special class for undefined entities. You can subclass this Undefined class from Jinja2 to include __getattr__ and other attribute accessors that you want to be able to use even on undefined entities and have them return a blank unicode string (for example).

Upvotes: 6

Related Questions