2009-04-13 8 views
12

En lugar de eliminar registros en mi aplicación Django, solo quiero marcarlos como "eliminados" y ocultarlos de mis consultas activas. Mi principal razón para hacerlo es dar al usuario una opción de recuperación en caso de que accidentalmente eliminen un registro (estos registros también pueden ser necesarios para un seguimiento de auditoría de back-end.)¿Cómo puedo marcar fácilmente los registros como eliminados en los modelos de Django en lugar de eliminarlos realmente?

Existen muchas relaciones de clave externa, por lo que Marcaré un registro como eliminado. Tendría que "conectar en cascada" esta bandera de eliminación a esos registros también. ¿Qué herramientas, proyectos existentes o métodos debo usar para hacer esto?

Respuesta

11

Django ofrece fuera de la caja el mecanismo exacto que está buscando.

Puede cambiar el administrador que se utiliza para acceder a través de objetos relacionados. Si su nuevo administrador personalizado filtra el objeto en un campo booleano, el objeto marcado como inactivo no se mostrará en sus solicitudes.

ver aquí para más detalles: http://docs.djangoproject.com/en/dev/topics/db/managers/#using-managers-for-related-object-access

+1

pero no creo que las búsquedas de otros objetos respeten esto. es decir, si busca desde un modelo relacionado, usará el administrador que ignora los registros eliminados. Eso significa que los registros marcados como eliminados seguirán teniendo sus relaciones intactas, lo que probablemente no sea lo que usted desea. – fastmultiplication

+0

@fastmultiplication Por "usará el administrador que ignora los registros eliminados", ¿quiere decir que ignorará el indicador eliminado, es decir, incluirá los registros eliminados? Ese es el comportamiento que estoy viendo. –

+2

derecha. El uso de administradores para controlar qué objetos son accesibles solo funciona cuando usa esa clase. Digamos que la clase A está usando un administrador para ocultar objetos "eliminados", luego 'A.objects' ocultará los borrados. Pero si A está relacionado con la clase B, 'B.filter (a__name = 'smith')' buscará todos los objetos A, incluso los eliminados. – fastmultiplication

4

Una buena pregunta, me he estado preguntando cómo hacer esto de manera eficiente.

No estoy seguro si esto hará el truco, pero django-reversion parece hacer lo que quiere, aunque es probable que desee examinar para ver cómo se logra este objetivo, ya que hay algunas formas ineficaces de hacerlo.

Otra idea sería tener la temida bandera booleana en sus Modelos y luego crear un administrador personalizado que agregue automáticamente el filtro, aunque esto no funcionaría para búsquedas en diferentes Modelos. Sin embargo, otra solución suggested here es tener modelos duplicados de todo, lo que parece exagerado, pero puede funcionar para usted. Los comentarios allí también discuten diferentes opciones.

Añadiré que, en general, no considero que ninguna de estas soluciones merezca la pena; Por lo general, lo asimilo y filtrar mis búsquedas en la bandera booleana. Evita muchos problemas que pueden surgir si intenta hacerse demasiado inteligente. Es un dolor y no muy seco, por supuesto. Una solución razonable sería una mezcla del administrador personalizado al tiempo que es consciente de sus limitaciones si intenta buscar un modelo relacionado a través de él.

+0

+1 - Nunca había oído hablar de este proyecto ... ¡la característica de deshacer solo es tentadora si es verdad! –

+0

django-reversión es genial, pero es una exageración absoluta en este caso, ¿no crees? Estamos hablando de revertir un estado booleano, no retroceder a una de las múltiples versiones almacenadas de un objeto. – ozan

+0

@ozan: "Añadiré que, en general, no considero que ninguna de estas soluciones valga la pena". –

3

Creo que usar una bandera booleana 'is_active' está bien, no es necesario que conecte la bandera a las entradas relacionadas en el nivel db, solo necesita seguir refiriéndose al estado del padre. Esto es lo que sucede con el modelo de usuario de contrib.auth, recuerde: marcar a un usuario como no activo no le pide a django que revise los modelos relacionados y mágicamente intenta desactivar los registros, sino que simplemente sigue revisando el atributo is_active del usuario correspondiente al artículo relacionado.

Por ejemplo, si cada usuario tiene muchos marcadores, y usted no desea que los marcadores de un usuario inactivo sean visibles, solo asegúrese de que bookmark.user.is_active sea verdadero. Es poco probable que sea necesario un indicador is_active en el marcador en sí.

0

Hay varios paquetes que proporcionan esta funcionalidad: https://www.djangopackages.com/grids/g/deletion/

Estoy desarrollando una https://github.com/meteozond/django-permanent/ Sustituye Gestor defecto y QuerySet eliminar los métodos para traer borrado lógico. Sombrea completamente los métodos de eliminación de Django predeterminados con una excepción: marca los modelos que se heredan de PermanentModel en lugar de la eliminación, incluso si su eliminación se debe a una relación.

Cuestiones relacionadas