“Lazy load” of data from a context processor

六月ゝ 毕业季﹏ 提交于 2019-11-28 10:06:51

Django has a SimpleLazyObject. In Django 1.3, this is used by the auth context processor (source code). This makes user available in the template context for every query, but the user is only accessed when the template contains {{ user }}.

You should be able to do something similar in your context processor.

from django.utils.functional import SimpleLazyObject
def my_context_processor(request):
    def complicated_query():
        do_stuff()
        return result

    return {
        'result': SimpleLazyObject(complicated_query)

If you pass a callable object into the template context, Django will evaluate it when it is used in the template. This provides one simple way to do laziness - just pass in callables:

def my_context_processor(request):
    def complicated_query():
        do_stuff()
        return result                      
    return {'result': complicated_query}

The problem with this is it does not memoize the call - if you use it multiple times, complicated_query gets called multiple times.

The fix is to use something like SimpleLazyObject as in the other answer, or to 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 produce some strange bugs sometimes.

(I was the one who originally implemented LazyObject and SimpleLazyObject, and discovered for myself that there is curse on any code artefact labelled simple.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!