Me gustaría generar automáticamente algún tipo de registro de todos los cambios en la base de datos que se realizan a través del shell de Django en el entorno de producción.
Utilizamos secuencias de comandos de migración de datos y esquemas para modificar la base de datos de producción y están controlados por versión. Por lo tanto, si introducimos un error, es fácil rastrearlo. Pero si un desarrollador del equipo cambia la base de datos a través del shell de Django, lo que luego presenta un problema, por el momento solo podemos esperar que recuerden lo que hicieron o que podamos encontrar sus comandos en el historial del shell de Python.
Ejemplo. Imaginemos que el siguiente código fue ejecutado por un desarrollador del equipo a través del shell de Python:
>>> tm = TeamMembership.objects.get(person=alice) >>> tm.end_date = date(2022,1,1) >>> tm.save()
Cambia un objeto de membresía de equipo en la base de datos. Me gustaría registrar esto de alguna manera.
Soy consciente de que hay un montón de paquetes de Django relacionados con el registro de auditoría , pero solo estoy interesado en los cambios que se activan desde el shell de Django, y quiero registrar el código de Python que actualizó los datos.
Así que las preguntas que tengo en mente:
pre_save
para todos los modelos para saber si los datos cambian, pero ¿cómo puedo saber si la fuente fue del shell de Python? ¿Cómo sé cuál era la declaración original de Python?Podrías usar la anotación del receiver
de Django.
Por ejemplo, si desea detectar alguna llamada del método save
, podría hacer:
from django.db.models.signals import post_save from django.dispatch import receiver import logging @receiver(post_save) def logg_save(sender, instance, **kwargs): logging.debug("whatever you want to log")
algo más de documentación para las señales
Yo consideraría algo como esto:
Envolviendo cada sesión de python con algún tipo de código de inicialización usando, por ejemplo, la variable de entorno PYTHONSTARTUP
https://docs.python.org/3/using/cmdline.html#envvar-PYTHONSTARTUP
En el archivo donde PYTHONSTARTUP
apunta al registro del controlador de salida usando atexit
https://docs.python.org/3/library/atexit.html
Estas dos cosas deberían permitirle usar algunas API de nivel inferior de django-reversion
para envolver toda la sesión de terminal con https://django-reversion.readthedocs.io/en/stable/api.html#creating-revisions (algo como esto pero llamando a __enter__
y __exit__
de ese administrador de contexto directamente en su código de inicio y atexit
). Desafortunadamente, no conozco los detalles, pero debería ser factible.
En atexit
/revision, finalice llamando al código para enumerar las líneas adicionales de la sesión de terminal y almacenándolas en otro lugar de la base de datos con una referencia a la revisión específica.
Ver:
https://docs.python.org/3/library/readline.html#readline.get_history_length
https://docs.python.org/3/library/readline.html#readline.get_history_item
Básicamente, la idea es que podrías llamar a get_history_length
dos veces: al principio y al final de la sesión de terminal. Eso le permitirá obtener líneas relevantes de dónde tuvo lugar el cambio usando get_history_item
. Puede terminar teniendo más líneas de historial de las que realmente necesita, pero al menos hay suficiente contexto para ver qué está pasando.