Django template context function without running automatically
Sorry or the confusing title! It's actually a lot simpler than it sounds.
I've got a function:
def get_messages(request):
# do something expensive with the request
return 'string'
I want to be able to call that function from the template, so I've strapped in with a context processor:
def context_processor(request):
return {'messages':get_messages(reques开发者_Go百科t)}
So now when I have {{messages}}
in my template, string
prints out. Great.
The problem is get_messages
is quite expensive and isn't always needed. Less than half the templates need it. Is there a way of passing the function to the template and leave it up to the template if it runs or not?
I tried this already:
def context_processor(request):
return {'messages':get_messages}
But that just outputs the function description <function get_messages at 0x23e97d0>
in the template instead of running it.
I think You shouldn't mix logic of application with template (the view in MVC pattern). This breaks consistency the architecture. You can call get_messages
in views that need it and simply pass messages
to the template context, in the others just pass None
.
But answering Your question: You can make a proxy object. E.g:
class Proxy(object):
def __init__(self, request)
self.request = request
super(Proxy, self).__init__()
def get_messages(self):
# so some expensive things
return 'string'
# context processor
def context_processor(request):
return {'messages':Proxy(request)}
# in the view
{{ messages.get_messages }}
You can make this ever more generic, and create Proxy class that has one method (e.g get
), and takes one parameter in constructor: a function which takes request object as first parameter. This way You gain generic method to proxy a function call in Your templates. Here it is:
class Proxy(object):
def __init__(self, request, function)
self.request = request
self.function = function
super(Proxy, self).__init__()
def get(self):
return self.function(self.request)
then You can write even cooler than I had written before:
# context processor
def context_processor(request):
return {'messages':Proxy(request, get_messages)}
# sounds nice to me
{{ messages.get }}
精彩评论