For the second time in a few years I've found myself doing a number of Django upgrades. It's a good thing: I'm happy the framework I chose to base most of my work on when I went solo has stayed relevant. But this time I wanted to document some of the pain points to make things easier on anyone else going through the same.
First off, this round of updates has been a lot easier than the first: back then I was the point of contact for WebFaction clients who had a Django app but no longer had a developer and those orphaned projects trended ancient. I started working with Django in 2009 with Django 1.1 and that was modern compared to most of the WebFaction projects. The biggest challenge in that group was a project running on 0.96 and using psycopg
. I'd been installing psycopg2
for so long at that point it never occurred to me there was a version before it. And the Internet felt the same way: obtaining a version of Django that old was a challenge (see this thread for how to get versions no longer listed in Pypi). Obtaining a copy of psycopg
proved impossible (I cheated and wound up downloading the folder from the client's site-packages
directory and using that to replicate the issue they were seeing-- definitely not a recommended approach).
virtualenv
or similar concept. If you're already doing so, great. If you are not, now is definitely the time to start. If you're doing anything more than a minor upgrade/ working on a project with no 3rd party libraries, you are going to run into some "dependency hell" where you've updated to Django 1.NEW and updated all your code to be compatible and then find out some libraries you use aren't compatible. The best case scenario is where you just need to update the libraries to their latest versions too, but you may have to play around with the versions to make it all work. Otherwise you need to figure out how to replace the library or fork it.virtualenv
suggestion is that you also use pip
to install packages and pip freeze
to create a requirements file with the exact versions of the libraries your project uses. virtualenv
is your friend: at one point I had three local environments for my site, tkc
(live), tkc16
and tkc110
. Once I finished the upgrade process, I deleted the first two and renamed tkc110
to tkc
and it was like nothing ever happened. Be aware of the long-term release versions and the deprecation schedule when targeting a new version.select_related
, prefetch_related
and only
for making queries faster.render_to_response
to render
. It will make things easier and the former is soon to be removed.virtualenv
and project with 1.10 (or similar) and then dragging your apps into the project. You will still need to update a bunch of stuff but it may make things a lot easier and help with your future-proofing.django.conf.urls.patterns
is gone and all view references in urls.py
need to be imported views, not string names.django.contrib.sites
is no longer included by default, which can cause a RuntimeError: Model class django.contrib.sites.models.Site doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS
. Just add it back to INSTALLED_APPS
.django.utils.log.NullHandler
was removed, replace the references with logging.NullHandlerTEMPLATES
setting replaces all TEMPLATE_*
settings. This is a bit of PITA as you have to move a bunch of things into their new home in that setting.select_related
actually checks that the fields exist on the model you are querying. Previously this just silently ignored the error and you were left thinking you'd improved performance when you weren't doing anything.django.contrib.formtools
is replaced by an external appurls.py
files changed: you now have to have url(regex, view)
instead of just (regex, view)
, otherwise you will get AttributeError 'tuple' object has no attribute 'regex'
. Make note of the changes in 1.10 to urls.py
files if you're going to be updating all of them anyway.request.REQUEST
was removed, but you weren't using that anyway, were you?'south'
from your INSTALLED_APPS
, you actually need to uninstall it from your virtualenv
or you will get errors like There is no South database module 'south.db.postgresql_psycopg2' for your database.
.wsgi
file project use changed. You may run into AppRegistryNotReady: Apps aren't loaded yet
. See this StackOverfloew thread.RuntimeError: populate() isn't reentrant
- there are a number of possible causes for this (and I'm not sure if there are all 1.7-specific). In my case it was a dumb error where I had an app listed twice in INSTALLED_APPS
.get_query_set
is now get_queryset
.django.contrib.localflavor
is gone, replaced by a 3rd-party app. Update your requirments file and your references.django.contrib.markup
is gone. You will need a replacement..raw_post_data
attribute on Request objects. Use .body
instead.SessionMiddleware
telling you a value isn't JSON-serializable, you need to swap back to the old way of handling sessions by adding this to your settings.py
: SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
User
model. A user in the reddit discussion of this post said it caused them problems due to a subclassed User
model in their project.{% url %}
tag changed and now the url name has to be quoted. If you use an editor that supports multi-file search-and-replace, you can update all your templates easily. Pro-tip: do this in its own branch or similar for safety's sake.ALLOWED_HOSTS
setting. Make sure to do this because it will bite you: the setting only applies if DEBUG = False
, so you won't run into errors locally but then your brand-new, updated site will not respond when you post it live.django.utils.simplejson
. Can do a search and replace to import json
instead. Unrelated to any upgrade stuff, if you do a lot of JSON processing or a little bit of JSON processing on very big pieces of JSON, take a look at ujson
. I've gotten a lot of free performance improvements from it.direct_to_template
is gone. Use this solution in its placeADMIN_MEDIA
is replaced by static files app from 1.3django.conf.urls.defaults
is replaced by django.conf.urls
. Update your urls.py
files accordingly.manage.py
. You may run into some errors like "The system cannot find the file X" until you restructure (or update how you reference urls, etc in the settings)."No modules named six"
- this is an annoying one I ran into with a couple 3rd party libraries. I was testing which versions I could easily update to by updating to 1.2.0, 1.3.0, 1.4.0, etc. The problem is six
was introduced in Django 1.4.2 so don't update to anything less than that if you're going to use 1.4.staticfiles
. If you've never dealt with that, it's a sea change and you will need to read the documentation about how to change things. Essentially, this was splitting up the idea of media (user-generated uploads) from your site's static assets.