Django 1.10 refinements

Posted by Alasdair Nicol on Mon 01 August 2016

Django 1.10 was released today. Instead of focussing on the new features, I'd like to focus on a couple of items from the features removed section of the release notes. With Django 1.10, we've reached the end of the line for deprecations started in Django 1.8, and I think the result is cleaner, less error-prone views and URL configs.

Simplified URL config

Django urls used to look like this:

urlpatterns = patterns('',
    (r'^articles/(\d{4})/$', 'news.views.year_archive'),

    url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive', name='month_archive'),

The prefix argument was often unused, so you had a confusing empty string at the begining. The patterns could be url() instances or tuples, and you could use either callables or strings for the views.

In Django 1.10, urlpatterns is simply a list of url() instances:

urlpatterns = [
    url(r'^articles/(\d{4})/$', views.year_archive),
    url(r'^articles/(\d{4})/(\d{2})/$', views.month_archive, name='month_archive'),

Support for passing the view as a string is removed, you must use the callable. It's much tidier now, and a great example of There should be one-- and preferably only one --obvious way to do it from the Zen of Python.

No more render_to_response with RequestContext

Template context processors allow you to add a variable to every template. For example, you might use the logged-in user when rendering the navigation menu.

The render and render_to_response shortcuts simplify the process of fetching a template and rendering it. Before Django 1.10, you could use template context processors with both shortcuts. The code with render is simply:

return render(request, 'my_template.html', {'foo': 'bar'})

However, with render_to_response, you had to manually use a request context:

return render_to_response('my_template.html', {'foo': 'bar'}, context_instance=RequestContext(request))

The render shortcut was introduced in Django 1.3, so there's been no good reason to use render_to_response for 5 years. However, I still see lots of code using render_to_response. If you forget the context_instance argument, then template context processors don't work. I've seen many beginners hit CSRF errors because of this.

In Django 1.10, the context_instance argument has been removed from render_to_response. This is a result of changes to Django templating in 1.8. This means that you must switch your views from render_to_response to render if you use template context processors.

While you're at it, you can convert code that uses render_to_response without a context_instance to use render. Just use request=None. For example:

return render_to_response(template, context)

is equivalent to:

return render(request=None, template=template, context=context)

I think now would be a good time to finally deprecate render_to_response and remove it. I understand that Django developers are wary of forcing unnecessary code churn on users. However, users already have to update any code that uses render_to_response with RequestContext before upgrading to Django 1.10, so now would be a good time to deprecate it so that we can eventually remove it completely.