Oli Warner About Contact Oli on Twitter Subscribe

Migrating Django’s database

Monday, 17 September 2012 django

Django is awesome but there’s one job that can be a bit trickier than you’re used to: moving from one database to another.

So let’s pretend that you want to move from SQLite3 to PostgreSQL. It’s a fairly common move for Django developers and I recently went through the process for one of my larger projects.

Your project’s settings should have something a little bit like this, pointing at the current database:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'database.sqlite3',
}
}

Sidebar: If you don’t have this, you’re still running on the old style of configuration. Take some time to upgrade everything to the latest Django. This tutorial assume you’re at version 1.4 and won’t work with the old style of database definition.

We need to add in the new database. We need to do this inline (as a new database) for reasons I’ll get to:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'database.sqlite3',
}
'new': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'database_name',
'USER': 'username',
'PASSWORD': 'password',
'HOST': ''
},
}

From here Django can access both databases.

Normally you should be able to run the following:

./manage.py dumpdata --database=default > data.json

./manage.py syncdb --all --database=new
./manage.py loaddata --database=new data.json

However, I ran into issues with this. contenttypes was schitzing-out. I had many errors but the main one was ContentType matching query does not exist. and I wasn’t getting anywhere.

All I needed to do was handle things separately. Migrate contenttypes first and then handle the rest of my data:

./manage.py dumpdata --database=default contenttypes > ctypes.json
./manage.py dumpdata --database=default --exclude contenttypes > data.json

./manage.py syncdb --all --database=new
./manage.py loaddata --database=new ctypes.json
./manage.py loaddata --database=new data.json

After that, just edit your settings. Rename new to default and then you can either remove the old default or rename it to something like old so you can quickly have access to it in the future.

Some people may have problems with some primary keys. You can include the argument --natural to use string-based keys but in my cases, I’ve only run into more problems with this method. Just splitting the data up has worked for me so far.