If you pass the called object to the template context, Django will evaluate it when it will be used in the template. This provides an easy way to do laziness - just go to callables:
def my_context_processor(request): def complicated_query(): do_stuff() return result return {'result': complicated_query}
The problem with this is that it does not memoize the call - if you use it several times, complicated_query is called several times.
The fix is ββto use something like SimpleLazyObject , as in another answer, or use something like this memoize decorator:
def memoize_nullary(f): """ Memoizes a function that takes no arguments. """ def func(): if not hasattr(func, 'retval'): func.retval = f() return func.retval return func def my_context_processor(request): @memoize_nullary def complicated_query(): do_stuff() return result return {'result': complicated_query}
Or, if the function already exists, you would do it like this:
from somewhere import complicated_query def my_context_processor(request): return {'result': memoize_nullary(complicated_query)}
I would prefer this method over SimpleLazyObject , because the latter can sometimes generate some strange errors .
(I was the one who originally implemented LazyObject and SimpleLazyObject , and discovered that there is a curse on any code artifact marked simple .)
spookylukey
source share