[Django]-Cannot resolve callable context variable

2đź‘Ť

âś…

Passing lambdas to the template in Django 1.2.4 worked fine, after upgrading my code to Django 1.3, I was bit by the same issue too. I gave up on trying to set alters_data flag and trying to apply the patch in ticket 15791 that adds a do_not_call_in_templates flag too (apparently merged in the dev version). The way I sidestepped the problem until a proper solution is in place was to use a factory function without arguments that returned the lambda instead of passing the lambda to the template.

def return_a_lambda():
    return lambda x : 'x=%s' % x

c = dict(f=return_a_lambda)
>>> c['f']
<function return_l at 0x33bc668>
template.Variable('f').resolve(c)
<function <lambda> at 0x33ccaa0>

Django’s template calls all context variables as long as they don’t need an argument, hence return_a_lambda is executed and the template gets the lambda in return.

https://docs.djangoproject.com/en/dev/ref/templates/api/ under “Rendering a context”

Update:
A reusable hack would be a factory function that returns a factory function:

def encapsulate(func):
    def wrapper():
        return func
    return wrapper

or a shorter version:

def encapsulate(func):
    return lambda: func

with the final code looking like this:

c = dict(f=encapsulate(lambda x : 'x=%s' % x))

which is easier to interpret. In my case (https://github.com/rosarior/mayan) I now have to do this some 30 times aprox to get the code running in Django 1.3 :'(

1đź‘Ť

here is a ticket that I found (that I have just reopened because I have found, I think, a “better” solution): https://code.djangoproject.com/ticket/15791

👤akonsu

0đź‘Ť

Odd, it works for me (using Django 1.3):

In [9]: from django import template
In [10]: c = dict(f = lambda x : 'x=%s' % x)

In [11]: c['f']
Out[11]: <function <lambda> at 0x00F9D670>

In [12]: template.Variable('f').resolve(c)
Out[12]: <function <lambda> at 0x00F9D670>

But out of curiosity, why use a dict instead of a django.template.context.Context?

In [19]: c = django.template.context.Context()

In [21]: c['f'] = lambda x: 'x=%s' % x

In [22]: template.Variable('f').resolve(c)
Out[22]: <function <lambda> at 0x01946730>

(I’d leave this as a comment but I don’t have quite enough rep yet).

Leave a comment