Notes on upgrading to Django 1.6 & 1.7

Django 1.7 was officially released this week, prompting me to dig into my live Django projects and see which were desperately in need of upgrading.

Fear of getting myself into trouble with the new migrations system made me hold back on some projects and upgrade them only as far as 1.6.7, but most projects were bumped all the way to 1.7. Here are a few notes on common changes you might have to make if you’re coming from older versions of Django, particularly 1.3 and 1.4.

New migrations system
The most major change introduced in 1.7. If your project uses South migrations you’ll need to follow the instructions here to generate new initial migrations for each app in your project. This seemed to work fine on the projects I upgraded to 1.7.

If you’re upgrading from a version of Django prior to 1.5, you’ll need to add the ALLOWED_HOSTS variable to your settings file, or Django will raise a SuspiciousOperation exception when you try to load your site.

New gunicorn init style
I was using an embarrassingly old version of gunicorn on some projects – 0.12.2, for example; the current version is 19.1.1 – and at some point the recommended init style changed from a management command ( run_gunicorn or run_gunicorn) to a standalone command: gunicorn myproject.wsgi. This references the WSGI application definition in your project’s created as part of the project generation process. If your project was created prior to Django 1.4, you’ll need to add your own file. Docs here; generated code from a sample project here – replace myproject with your project name.

You’ll need to change the init style in any process manager you might be using, such as Supervisor, and also in your Procfile if you’re using Heroku. E.g. from this:web: collectstatic --noinput; run_gunicorn -b "$PORT" -w 4 To this: web: collectstatic --noinput; gunicorn myproject.wsgi -b "$PORT" -w 4

Adding new style test runner
Your test runner now needs to be explicitly declared in your project settings, so I found I needed to add the following setting to prevent a warning message (source):TEST_RUNNER = 'django.test.runner.DiscoverRunner'

Updating {% url %} template tag style
If you’re upgrading from prior to 1.5, you’ll need to quote route names and view paths passed to the url template tag – e.g from {% url %} to {% url ‘’ %}.

Replacing direct_to_template with TemplateView
Earlier versions of Django supported the direct_to_template shortcut to quickly render a template without a view – this has now been removed in favour of the TemplateView Class-Based View. If you have any URL patterns that look like this:url(r'^404/$', direct_to_template, {'template': '404.html'}),
url(r'^robots\.txt$', direct_to_template, {'template':'robots.txt', 'mimetype':'text/plain’}),
You should replace them with this: url(r'^404/$', TemplateView.as_view(template_name="404.html”)),
url(r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', content_type='text/plain’)),

Virtualenvs losing their setuptools
During some larger upgrade runs on my development box, pip would occasionally drop the ball and refuse to perform any operations, giving the error ImportError: No module named pkg_resources. Reinstalling setuptools using the advice here sorted it.

Quickly upgrade all packages in requirements.txt
Lastly, I found for most projects I wanted to upgrade all the packages listed in requirements.txt (which includes pinned versions) — but pip doesn’t yet have a one-stop command for this. I found that something like this usually worked: cat requirements.txt | grep -v '^-e' | awk 'BEGIN{FS="=="}{print $1}' | xargs pip install --upgradeI’ve since discovered the existence of pip-tools which has a command that takes care of this for you.

You’ll probably find a few other bits and pieces that need adjustment before your project will work perfectly with Django 1.7, but hopefully this covers some of the more common cases.