SoFunction
Updated on 2025-03-02

How to set variables in Django's context

The example in the previous section simply returns a value. It is also useful to set a template variable instead of a return value. In that case, the template author can only use the variables set by your template tag.

To set variables in the context, use a dictionary assignment on the context object of the render() function. Here is a modified CurrentTimeNode , which sets a template variable current_time and does not return it:

class CurrentTimeNode2():
  def __init__(self, format_string):
    self.format_string = str(format_string)

  def render(self, context):
    now = ()
    context['current_time'] = (self.format_string)
    return ''

(We leave the work of creating the function do_current_time2 and registering the current_time2 template tag as reader exercises.)

Note render() returns an empty string. render() should always return a string, so if the template tag is just to set variables, render() should return an empty string.

You should use this new version of the tag like this:

{% current_time2 "%Y-%M-%d %I:%M %p" %}
<p>The time is {{ current_time }}.</p>

But CurrentTimeNode2 has a problem: the variable name current_time is hardcoded. This means you have to make sure that your template doesn't use {{ current_time }} anywhere else, because {% current_time2 %} will blindly override the value of that variable.

A simpler solution is to specify the name of the variable that needs to be set by the template tag, like this:

{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>

To do this, you need to refactor the compiled functions and Node classes as follows:

import re

class CurrentTimeNode3():
  def __init__(self, format_string, var_name):
    self.format_string = str(format_string)
    self.var_name = var_name

  def render(self, context):
    now = ()
    context[self.var_name] = (self.format_string)
    return ''

def do_current_time(parser, token):
  # This version uses a regular expression to parse tag contents.
  try:
    # Splitting by None == splitting by spaces.
    tag_name, arg = (None, 1)
  except ValueError:
    msg = '%r tag requires arguments' % [0]
    raise (msg)

  m = (r'(.*?) as (\w+)', arg)
  if m:
    fmt, var_name = ()
  else:
    msg = '%r tag had invalid arguments' % tag_name
    raise (msg)

  if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):
    msg = "%r tag's argument should be in quotes" % tag_name
    raise (msg)

  return CurrentTimeNode3(fmt[1:-1], var_name)

Now do_current_time() passes the format string and variable name to CurrentTimeNode3 .