Django url arguments template access and extra options

Problem

You want to access url parameters and extra options inside a Django template

Solution

Use regular expressions and Django's special syntax to handle url parameters or the url options dictionary to define url extra options. Once added as parameters, you can access the values inside Django templates.

How it works

In a previous recipe you learned how Django uses regular expressions to match url patterns and send requests directly to a template. This exercise though was limited to discarding the url information after the initial pattern match. If you didn't do this last exercise see the recipe 'Set up content, understand Django urls, templates and apps'.

Sometimes it's helpful or even necessary to pass url information to the backing template. For example, if you have several urls like /drinks/mocha, /drinks/espresso and /drinks/latte, the last part of the url illustrates a pattern. In this case mocha, espresso and latte refer to types of drinks. It can be helpful or necessary to relay this url information to the backing template to display it or use it in some other way. This process requires that part of the url be treated as a parameter.

To handle url parameters Django uses a special syntax in combination with regular expressions. Listing 1 shows a url example that creates a parameter named drink_type.

Listing 1 - Django url parameter definition

urlpatterns = [
    url(r'^drinks/(?P<drink_type>\D+)/',TemplateView.as_view(template_name='drinks/index.html')),
]
Note Parameter values can match any regular expression

The url in listing 1 creates a variable only if the value matches the specified regular expression (i.e. non-digits \D+). But be aware you can broaden or restrict this pattern with any regular expression, like regular Django url patterns. See the appendix Regular expressions for Django Urls for more examples.

Notice the (?P<drink_type>\D+) syntax in listing 1. The ?P tells Django to convert the matching value to a parameter and <drink_type> assigns the matching value to a variable called drink_type. The final piece of the url parameter syntax \D+ is a regular expression to determine the matching value, in this case the matching value are non-digit characters (i.e.letters).

The important functionality of the syntax in listing 1 is the matching url value is treated as a parameter. For example, for the url /drinks/mocha the value mocha is assigned to the drink_type parameter, for the url /drinks/espresso the value espresso is passed to the drink_type parameter. For a url like /drinks/123 the regular expression pattern doesn't match -- because 123 are digits -- so no action is taken.

If a url match occurs for listing 1, the request is sent directly to the template drinks/index.html. Django provides all parameters defined in this manner through a Django template variable with the same name. Therefore to access a parameter called drink_type inside a template you use the syntax {{drink_type}} as illustrated in listing 2 -- the {{}} syntax interprets the variable name to output its value.

Listing 2 - Django template variable access url parameter

Drink {{drink_type}}

In addition to treating parts of a url as parameters, it's also possible to define extra options in the url definition for direct access inside a Django template. These extra options are defined inside the general purpose dictionary declared as the last part of the url definition.

For example, you can change listing 1 to url(r'^drinks/(?P\D+)', TemplateView.as_view(template_name='drinks/index.html'), {'onsale':True}), -- notice you just add a dictionary with key-values at the end. In this manner the onsale key becomes a url extra option, which is passed to the underlying template.

Url extra options are assigned like url parameters. So to access a url extra option inside a template you use the same syntax. The url extra option {'onsale':True} is accessed with the syntax {{onsale}}.

Note Don't try to treat url parameters separated by ? and & as Django url parameters

On certain urls -- those made by HTTP GET requests -- parameters are added to a url with ? followed by parameter_name=parameter_value separated by & (e.g./drinks/mocha?type=cold&size=large). While it could be possible to treat the parameters separated by ? and & as Django url parameters, the regular expression required for this is very complex.

Url parameters of this kind should be accessed in Django view methods -- explored in the next recipe -- where this type of parameter extraction is easier. Or the url parameters should be changed to accommodate a simpler regular expression. For example /drinks/mocha/cold/large instead of /drinks/mocha?type=cold&size=large.