Señales de Django frente a anular método de guardado

Estoy teniendo problemas para envolver mi cabeza alrededor de esto. Ahora mismo tengo algunos modelos que se parecen a esto:

def Review(models.Model) ...fields... overall_score = models.FloatField(blank=True) def Score(models.Model) review = models.ForeignKey(Review) question = models.TextField() grade = models.IntegerField() 

Una revisión tiene varios “puntajes”, el puntaje general es el promedio de los puntajes. Cuando se guarda una revisión o un puntaje, debo recalcular el promedio general de puntuación. En este momento estoy usando un método de guardar anulado. ¿Habría algún beneficio al usar el despachador de señales de Django?

Las señales de guardar / eliminar son generalmente favorables en situaciones en las que necesita realizar cambios que no son completamente específicos del modelo en cuestión, o podrían aplicarse a modelos que tienen algo en común, o podrían configurarse para su uso en todos los modelos.

Una tarea común en los métodos de save anulados es la generación automatizada de slugs desde algún campo de texto en un modelo. Ese es un ejemplo de algo que, si necesitara implementarlo para varios modelos, se beneficiaría con el uso de una señal de pre_save , donde el controlador de señales podría tomar el nombre del campo de slug y el nombre del campo para generar el slug desde . Una vez que tenga algo así en su lugar, cualquier funcionalidad mejorada que ponga en su lugar también se aplicará a todos los modelos, por ejemplo, al buscar la babosa que está a punto de agregar para el tipo de modelo en cuestión, para garantizar la exclusividad.

Las aplicaciones reutilizables a menudo se benefician del uso de señales: si la funcionalidad que proporcionan puede aplicarse a cualquier modelo, generalmente (a menos que sea inevitable) no querrán que los usuarios modifiquen directamente sus modelos para beneficiarse de ellos.

Con django-mptt , por ejemplo, usé la señal pre_save para administrar un conjunto de campos que describen una estructura de árbol para el modelo que está a punto de crearse o actualizarse y la señal pre_delete para eliminar los detalles de la estructura de árbol para el objeto que se está eliminando y todo su subárbol de objetos antes de él y se eliminan. Debido al uso de señales, los usuarios no tienen que agregar o modificar los métodos de save o delete en sus modelos para que esta administración se haga por ellos, solo tienen que informar a django-mptt qué modelos desean que administre.

Tu preguntaste:

¿Habría algún beneficio al usar el despachador de señales de Django?

Encontré esto en los documentos de django:

Los métodos de modelo anulados no se llaman en operaciones masivas

Tenga en cuenta que el método delete () para un objeto no se llama necesariamente cuando se eliminan objetos de forma masiva utilizando un QuerySet o como resultado de una eliminación en cascada. Para garantizar que la lógica de eliminación personalizada se ejecute, puede usar señales pre_delete y / o post_delete.

Desafortunadamente, no hay una solución alternativa al crear o actualizar objetos de forma masiva, ya que no se llama a ninguno de save (), pre_save y post_save.

Desde: Anular métodos de modelo predefinidos

Si utiliza señales, podrá actualizar la puntuación de Revisión cada vez que se guarde el modelo de puntuación relacionado. Pero si no necesito tal funcionalidad, no veo ninguna razón para poner esto en señal, eso es algo muy relacionado con el modelo.

Es una especie de desnormalización. Mira esta bonita solución . Definición de campo de composición in situ.

Pequeña adición de los documentos de Django sobre el método de eliminación masiva ( .delete() en objetos QuerySet ):

Tenga en cuenta que esto, siempre que sea posible, se ejecutará únicamente en SQL, por lo que los métodos delete () de instancias de objetos individuales no se llamarán necesariamente durante el proceso. Si ha proporcionado un método de eliminación personalizado () en una clase de modelo y desea asegurarse de que se llame, deberá eliminar “manualmente” las instancias de ese modelo (p. Ej., Mediante la iteración sobre un QuerySet y llamando a eliminar () en cada objeto individualmente) en lugar de usar el método de eliminación masiva () de un QuerySet.

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

Y método de actualización masiva ( .update() en objetos QuerySet ):

Finalmente, tenga en cuenta que update () realiza una actualización en el nivel SQL y, por lo tanto, no llama a ningún método save () en sus modelos, ni emite las señales pre_save o post_save (que son una consecuencia de llamar a Model.save ( )). Si desea actualizar un montón de registros para un modelo que tiene un método personalizado de guardar (), recórtelos y llame a guardar ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update

Las señales son útiles cuando tiene que ejecutar algún proceso a largo plazo y no quiere bloquear a su usuario que espera a que se complete el proceso de guardar.