2011-01-20 16 views
5

Me gustaría realizar un seguimiento de qué campo ha cambiado en cualquier modelo (es decir, auditoría a nivel de modelo ya que es más atómico, no en admin/form-level como lo que django y django-reversión ya pueden hacer). Puedo hacer eso para cualquier campo utilizando señales de guardar/eliminar pre/post. Sin embargo, tengo un problema de hacer eso en un campo m2m.Django: no se pueden detectar cambios en campo muchos a muchos con señal m2m_changed - auditoría en el modelo

Para el siguiente ejemplo de código, defino el campo m2m 'custom_groups' en forma de cambio de usuario ya que es una relación inversa. Cuando el usuario guarda el formulario en la interfaz de administrador, por ejemplo, me gustaría iniciar sesión si hay un cambio en el campo 'custom_groups'.

Modelo:

from django.contrib.auth.models import User 

class CustomGroup(models.Model): 
    users = models.ManyToManyField(User, related_name='custom_groups') 

ModelForm:

class CustomUserChangeForm(UserChangeForm): 
    custom_groups = forms.ModelMultipleChoiceField(required=False, queryset=CustomGroup.objects.all()) 

El problema con el uso de señales m2m_changed es que no puedo comprobar qué ha cambiado realmente para el caso en el campo M2M se actualiza mediante el operador de asignación:

user.custom_groups = self.cleaned_data['custom_groups'] 

Esto se debe a que internamente django realizará un clear() en * custom_groups *, antes de agregar manualmente todos los objetos. Esto ejecutará pre/post-clear y luego pre/post save en el campo m2m.

¿Estoy haciendo todo esto de la manera incorrecta? ¿Hay un método más simple que realmente funcione?

Gracias!

+0

Aquí está mi solución http://stackoverflow.com/questions/1221878/why-does-django-post-save-signal-give-me-pre-save-data/9172783#9172783 – Fatih

Respuesta

12

Tuve un problema similar y creo que podría resolverlo. No sé cómo se está utilizando el m2m_changed pero debería estar en models.py y debería ser similar a algo como esto:

signals.m2m_changed.connect(your_function, sender=CustomGroup.users.through) 

Ahora, me gustaría crear un archivo que contiene signals.py esa función, y el siguiente código debe imprimir que las opciones que ha seleccionado:

def your_function(sender, instance, action, reverse, model, pk_set, **kwargs): 
    if action == 'post_add': 
     for val in pk_set: 
      print val 

Ahora, usted sabe que los valores actualizados. Espero que esto pueda resolver tu problema.

Cuestiones relacionadas