2011-01-20 11 views
5

Mi piacerebbe tenere traccia di quale campo è stato modificato su qualsiasi modello (ad esempio audit a livello di modello poiché è più atomico, non a livello di admin/form come quello che il django e il django-reversion possono già fare). Sono in grado di farlo per qualsiasi campo usando i segnali pre/post salva/cancella. Tuttavia, ho un problema a farlo su un campo m2m.Django: impossibile rilevare le modifiche sul campo molti-a-molti con il segnale m2m_changed - auditing a livello di modello

Per il seguente esempio di codice, definisco il campo m2m "custom_groups" nella forma di modifica utente poiché si tratta di una relazione inversa. Ad esempio, quando l'utente salva il modulo sull'interfaccia di amministrazione, vorrei registrare se c'è una modifica nel campo "custom_groups".

Modello:

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()) 

Il problema con l'utilizzo del segnale m2m_changed è che non riesco a controllare ciò che è effettivamente cambiato per il caso in cui il campo m2m viene aggiornato utilizzando l'operatore di assegnazione:

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

Questo perché internamente Django eseguirà un clear() su * custom_groups *, prima di aggiungere manualmente tutti gli oggetti. Questo eseguirà pre/post-clear e quindi pre/post salva sul campo m2m.

Sto facendo tutto questo nel modo sbagliato? Esiste un metodo più semplice che può effettivamente funzionare?

Grazie!

+0

Ecco la mia soluzione http://stackoverflow.com/questions/1221878/why-does-django-post-save-signal-give-me-pre-save-data/9172783#9172783 – Fatih

risposta

12

Ho avuto un problema simile e penso di poterlo risolvere. Non so come si utilizza il m2m_changed ma dovrebbe essere sul models.py e dovrebbe essere simile a qualcosa di simile:

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

Ora, vorrei creare un file signals.py contenente quella funzione, e il seguente codice dovrebbe stampare voi le opzioni che sono state selezionate:

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

Ora, si conoscono i valori aggiornati. Spero che questo possa risolvere il tuo problema.

Problemi correlati