text: The idea with template context processors in Django is to inject some defaults thing to be available when rendering a template that is rendered with a request.
  I.e. instead of...:
  def view1(request): context = { 'name': 'View 1', 'on_dev_server': request.get_host() in settings.DEV_HOSTNAMES } return render(request, 'view1.html', context) def view2(request): context = { 'name': 'View 2', 'other': 'things', 'on_dev_server': request.get_host() in settings.DEV_HOSTNAMES } return render(request, 'view2.html', context)
  And in your nominal
  templates/base.html you might have something like this:
  ... <footer> <p>© You 2015</p> {% if on_dev_server %} <p color="red">Note! We're currently on a dev server!</p> {% endif %} </footer> ...
  Instead you do this trick; in your
  settings.py you write down the list of defaults plus the one you want to always have available:
  TEMPLATE_CONTEXT_PROCESSORS = ( "django.contrib.auth.context_processors.auth", "django.template.context_processors.static", "myproject.myapp.context_processors.debug_info", )
  And to accompany that you define your
  myprojects/myapp/context_processors.py like so:
  def debug_info(request): return { 'on_dev_server': request.get_host() in settings.DEV_HOSTNAMES, }
  So far so good.
  However, there's a problem with this. Two problems in fact.
  First problem is that when all the templates in your big complicated website renders, it's quite possible that some pages don't need everything you set up in your context processors. That might mean a heck of a lot of extra computation when it won't ever be displayed.
  For example, I have a project where most pages have a sidebar where I show "Trending Events" which is something I compute in a
  context_processors.py function called
  def sidebar_events(request):. But the sidebar is not always shown and on the pages where it's not shown it's a waste to compute the stuff that
  sidebar_events computes. Also, I have management pages which uses a totally different
  base.html template. So there's a big chance you're wasting precious CPU.
  Another problem is that of code-readability (aka. how frustrating is this to debug for someone else or yourself after months of idle activity). If you're skimming through your
  base.html and you see this "random" variable called
  on_dev_server it's very very hard to tell where the heck that's defined. Hopefully grepping the whole source code is a way to go. A much better way to solve that problem would be sensible namespace naming.
  And also, by being too liberal with globally scoped variables there's a chance you might clash from a different piece of functionality that uses the same variable names. That chance is smaller when you use namespaces.
  So, to remedy this, let your template context processor functions return closures. It wraps the
  request automagically.
  Let's rewrite our trivial example from above, the
  context_processors.py should now look like this:
  def debug_info(request): def inner(): return { 'on_dev_server': request.get_host() in settings.DEV_HOSTNAMES, } return {'debug_info': inner}
  Now executing that becomes more optional and more deliberate in the template instead. E.g.
  ... <footer> <p>© You 2015</p> {% set debug_info = debug_info() %} {% if debug_info['on_dev_server'] %} <p color="red">Note! We're currently on a dev server!</p> {% endif %} </footer> ...
  This makes it more explicity which is a good thing. It also has the potential to be avoided if the stuff in there isn't needed in some templates.
  Follow @peterbe on Twitter
  Is « {% set debug_info = debug_info() %} » legal in Django templates ?
  You know what, that's Jinja syntax. Imagine the equivalent in Django templates :)
  Wouldn't be better to implement this with templatetags? As you said, context processors are for inserting variables for all your templates so, instead of doing that, why not write a templatetag and call whenever you need it?
  It's not a bad point but isn't templatetags (that take in the request for context) there to inject content into the template? With template context processors you get *information* which you then deliberately insert into the template when you will.
  I get your point. I guess there is a thin line between when to use one or the other in these cases but in my opinion, template tags feel less hacky than using closures for context processors. Mb some1 else can give his opinion ^^.
  This is the difference between a filter or simple_tag and an assignment_tag. Definitely agree that if performance is a consideration, this is more cleanly accomplished with an assignment tag.
  I don't even know what an "assignment_tag" is.
  I've been living in Jinja-land so long that maybe this is a newfangled feature in modern Django templates.
  Even though it was already possible to write such a tag before assignment_tag is indeed a pretty new feature it's only 3 years old
  An extra trick to use with this is to memoize the closure so that it is only called once if used multiple times. I use this decorator to convert closures into memoized ones:
  def memoize_nullary(f):
  """
  Memoizes a function that takes no arguments. The memoization lasts only as
  long as we hold a reference to the return value.
  """
  def func():
  if not hasattr(func, 'retval'):
  func.retval = f()
  return func.retval
  return func
  Why not a simple lazy object?
  from django.utils.functional import SimpleLazyObject
  def debug_info(request):
  return {
  'on_dev_server': SimpleLazyObject(lambda: request.get_host() in settings.DEV_HOSTNAMES),
  }
  The lambda won't be executed until needed and then the result will be inserted in the object's dlegation chain instead of the lambda.
  >>> s = SimpleLazyObject(lambda: True)
  >>> s
  <SimpleLazyObject: <function <lambda> at ...>>
  >>> if s: print 8
  ...
  8
  >>> s
  <SimpleLazyObject: True>
  >>>
  >>> s = SimpleLazyObject(lambda: False)
  >>> s
  <SimpleLazyObject: <function <lambda> at ...>>
  >>> if s: print 8
  ...
  >>> s
  <SimpleLazyObject: False>
  >>>