When setting up a new Django or Wagtail website, I also setup a backup procedure. Instead of writing a custom shell script to do so, I tend us use django-dbbackup for doing the hard work.

Setting it up is a breeze and should only take you a couple of minutes to do.

First, start with installing the package (don't forget to add it to your requirements.txt file):

$ pip install django-dbbackup

Once the package is installed, we need to update our Django configuration. We first need to add the module to the INSTALLED_APPS list:

mysite/settings.py

INSTALLED_APPS = (
    ...
    'dbbackup',
    ...
)

We also need to add a couple of configuration settings. Here's how i configured it for my sites:

mysite/settings.py

DBBACKUP_STORAGE = 'django.core.files.storage.FileSystemStorage'
DBBACKUP_STORAGE_OPTIONS = {
    'location': os.path.join(BASE_DIR, 'backup')
}
DBBACKUP_FILENAME_TEMPLATE = '{datetime}-{databasename}.{extension}'
DBBACKUP_MEDIA_FILENAME_TEMPLATE = '{datetime}-media.{extension}'

The DBBACKUP_STORAGE tells the system that I want to backup to the local filesystem. The DBBACKUP_STORAGE_OPTIONS define the location where to store the backups. If you prefer another location than the local filesystem, you can check if any of the other providers are more suited for you. Next to the local filesystem, also Amazon S3, Google Cloud Storage, Dropbox, FTP and SFTP are supported.

I also used the settings DBBACKUP_FILENAME_TEMPLATE and DBBACKUP_MEDIA_FILENAME_TEMPLATE to change the format of the filenames it generates. I prefer that the filenames start with the date in reverse so that they sort nicely.

To perform the database backup, you can run the dbbackup manage command:

$ ./manage.py dbbackup -z
Backing Up Database: /tmp/tmp.x0kN9sYSqk
Backup size: 3.3 KiB
Writing file to tmp-zuluvm-2016-07-29-100954.dump.gz

The -z option is optional and is used to compress the backup. This will create a dump of the database and store it in thee backup directory we have specified.

If you are allowing custom uploads in your site, you will have a media directly as will which needs to be backed up. That's also covered by the mediabackup command:

$ ./manage.py mediabackup
Backup size: 10.0 KiB
Writing file to zuluvm-2016-07-04-081612.tar

There are also the opposite commands, dbrestore and mediarestore to restore the backup:

$ ./manage.py dbrestore
Restoring backup for database: /tmp/tmp.x0kN9sYSqk
Finding latest backup
Restoring: tmp-zuluvm-2016-07-29-100954.dump
Restore tempfile created: 3.3 KiB
$ ./manage.py mediarestore
Restoring backup for media files
Finding latest backup
Reading file zuluvm-2016-07-04-082551.tar
Restoring: zuluvm-2016-07-04-082551.tar
Backup size: 10.0 KiB
Are you sure you want to continue? [Y/n]
2 file(s) restored

When you run these commands, the latest backup will be retrieved and restored.

To get the inventory of the available backups, you can use listbackups:

$ ./manage.py listbackups
Name                                     Datetime            
2020-11-22-185436-default.psql.gz        11/22/20 18:54:36   
2020-11-22-185456-media.tar.gz           11/22/20 18:54:56   
2020-11-22-185105-default.psql.gz        11/22/20 18:51:05   
2020-11-22-185402-media.tar.gz           11/22/20 18:54:02   

What I particularly like is how nicely it integrates with the Django stack. It read the database connection details from the Django settings. You can also call the backup from code using call_command, … There shouldn't be any reason anymore to not integrate a proper backup :-)