jueves, 24 de diciembre de 2020

¿Cómo generar backups Django desde archivo Python?


 A continuación el código para generar nuestros backups en Django. Lo incluimos en una tarea automatizada para que el código se ejecute automáticamente cada cierto tiempo. Es necesario que el código sea ejecutado en nuestro entorno virtual.

Para ello hacemos uso de la librería pathlib, útil para trabajar con rutas de archivos y directorios. Ofrece un sin número de método adecuados a la plataforma. Según su documentación, este módulo ofrece clases que representan rutas del sistema de archivos con semántica apropiada para diferentes sistemas operativos. Las clases de ruta se dividen entre rutas puras , que proporcionan operaciones puramente computacionales sin E/S, y rutas concretas , que heredan de rutas puras pero también proporcionan operaciones de E/S.

Y también de hacemos uso de la librería zipfile para comprimir nuestros backups en archivos .zip.


import os
import datetime


from pathlib import Path # https://docs.python.org/3/library/pathlib.html
from zipfile import ZipFile # https://docs.python.org/3/library/zipfile.html


# Importamos los settings de nuestro proyecto.
from app.settings import (setting1, setting2, setting3)

SETTINGS = (setting1, setting2, setting3)

# Directorio donde serán almacenados las copias de seguridad.
BACKUP_DIR_NAME = Path(__file__).resolve().parent.parent / "backups"

# Sufijo que tendrá el nombre del archivo generado Ej. nombre_20201224.zip
FILE_SUFFIX_DATE_FORMAT = "%Y%m%d"

# Cantidad de días que durará una copia de seguridad
# almacenada antes de proceder a borrarla automáticamente.
DAYS_TO_KEEP_BACKUP = 3

# Usaremos esta fecha para comparar los archivos antiguos que serán eliminados.
back_date = datetime.datetime.now() - datetime.timedelta(days=DAYS_TO_KEEP_BACKUP)
back_date = back_date.strftime(FILE_SUFFIX_DATE_FORMAT)


# Eliminamos primero para asegurarnos de que casi siempre haya
# espacio disponible para los nuevos backups que serán creados.

for setting in SETTINGS:
path = BACKUP_DIR_NAME

    # Suponiendo hemos creado una variable NAME en cada uno de nuestros setting
prefix = setting.NAME + "_"

# Listamos los archivos dentro del directorio donde se guardan los backups.
list_files = path.iterdir()

for f in list_files:
if f.suffix.lower() == ".zip":

try:
suffix = f.name.split("_")[1].split(".")[0]
except (IndexError):
# Si el archivo no tiene la estructura 'name_%Y%m%d.zip'
# entonces no es un archivo que se ha generado aquí.
continue
# Comparamos las fechas de tipo string y funciona ya que:
# '20201221' es menor que '20201224.
if suffix < back_date:
print(f"Eliminando: {f}")
f.unlink(missing_ok=True)



# Ahora procedemos a generar nuestros backups.

for setting in SETTINGS:

# Construimos el nombre que tendrá el archivo de salida, de acuerdo
# a este formato: 'filename_%Y%m%d.json' -> 'ininstancia_20201224.json'.
timestamp = datetime.datetime.now().strftime(FILE_SUFFIX_DATE_FORMAT)
backup_filename = BACKUP_DIR_NAME / f"{setting.NAME}_{timestamp}.json"

# Ejecutamos el comando python manage.py dumpdata...
print(f"dumpdata para {setting.NAME}")
os.system(f"python manage.py dumpdata > {backup_filename}")

# Creamos el archivo .zip y eliminamos el .json.
zip_filename = backup_filename.with_suffix(".zip")
with ZipFile(zip_filename, 'w') as zip:
zip.write(backup_filename, backup_filename.name)

# Eliminamos el archivos .json.
backup_filename.unlink(missing_ok=True)

print(zip_filename, "OK")

No hay comentarios.:

Publicar un comentario