How to Backup Django Database to Amazon S3 Automatically and Restore

December 15, 2019

How traumatizing would it be to lose all your data? How can we prevent this from happening? In this blog article, we will go through the steps together with you on how to set up an automatic backupper by one of the easiest ways possible, and we will automatize the process with Celery.

The process is as follows:

  1. Taking the database backup to the local environment
  2. Start making backups to Amazon S3
  3. Restoring the database
  4. Automate the backup process
  5. Media backing up

1- Taking the database backup to the local environment

Let’s start by installing some packages we will need.

pip install django-dbbackup celery boto django-storages

Storage settings and location settings needs to be added to your project’s settings.py.


settings.py
---

INSTALLED_APPS = [
...
"dbbackup",
...
]

...

DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage"
DBBACKUP_STORAGE_OPTIONS = {
"location": "{project path}/backups/"
}

Then run the command below. (Your backup will appear in the location that you set above.)

python manage.py dbbackup

2- Start making backups to Amazon S3.

Firstly, we need an Amazon S3 budget. You can create the budget using the link below. Be sure to grant access to Django in Amazon S3.

https://s3.console.aws.amazon.com/s3/

Then, you only need to change settings that we just added to in settings.py like below and run “python manage.py dbbackup” again.


settings.py
---

DBBACKUP_STORAGE = "storages.backends.s3boto.S3BotoStorage"
DBBACKUP_STORAGE_OPTIONS = {
"access_key": "{AWS-ACCESS-KEY}",
"secret_key": "{AWS-SECRET-KEY}",
"bucket_name": "{bucket-name}"
}

  • We have decided to keep our backups on Amazon but you can use any other storage platform like Dropbox, Drive or FTP etc using a similar method.

3- Restoring the database

Restoring is as easy as making backup. It requires just a command to run. With “python manage.py dbrestore” command, you can restore the latest backup.

It is also possible to see previous backups and return to those backups. With “python manage.py listbackups”, you can display the backup list and with “python manage.py dbrestore -i {file-name}” you can restore your backup anytime.

4- Automate the backing up

You will receive assistance from a Celery worker to automate the backup process. Basic code snippets below are some basic guidelines.

In our example, we set automated daily back up once a day at 19:30. Depending on your preferences, you can adjust and manage the frequency to your liking.

project > celery.py
---

from __future__ import absolute_import, unicode_literals

import os

from celery import Celery
from celery.schedules import crontab

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")
app = Celery("project_name")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()
app.conf.beat_schedule = {
# Everyday at 04:30
"backup": {
"task": "core.tasks.backup",
"schedule": crontab(hour=4, minute=30)
},
}


core > tasks.py
---
import datetime

from celery import shared_task

from django.conf import settings
from django.core.management import call_command


@shared_task
def backup():
if settings.DEBUG is True:
return f"Could not be backed up: Debug is True"
try:
call_command("dbbackup")
return f"Backed up successfully: {datetime.datetime.now()}"
except:
return f"Could not be backed up: {datetime.datetime.now()}"

Backups work when DEBUG is False. If you set DEBUG is True, you will see the log “Could not be backed up: Debug is True”. You just need to set DEBUG is False and everything is fine.

5- Media backing up

DBbackup provides backups of media files such as database with a single command without any extra settings. “python manage.py mediabackup” and “python manage.py mediarestore”. If it is wanted, media backing up also can be included to Celery.


project > celery.py
---
...
app.conf.beat_schedule = {
# Everyday at 04:30
"backup": {
"task": "core.tasks.backup",
"schedule": crontab(hour=4, minute=30)
},
# Every Monday at 4:40
"mediabackup": {
"task": "core.tasks.mediabackup",
"schedule": crontab(hour=4, minute=40, day_of_week=1)
},
}
...


core > tasks.py
---
...
@shared_task
def mediabackup():
if settings.DEBUG is True:
return f"Could not be backed up: Debug is True"
try:
call_command("mediabackup")
return f"Backed up successfully: {datetime.datetime.now()}"
except:
return f"Could not be backed up: {datetime.datetime.now()}"
...