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.