2016-02-10 14 views
9

In Django voglio tenere traccia di come i gruppi sono assegnati all'utente, in questo momento stiamo assegnando un gruppo di utenti tramite Django Admin. Ho provato ad usare il segnale m2m_changed sulla tabella User.groups.through ma nell'amministratore di Django quando il gruppo è stato assegnato all'Utente, prima elimina i gruppi esistenti di utenti e aggiunge gruppi aggiornati in modo da creare chiamate non necessarie all'azione "pre_clear" e "post_clear" di segnale così a causa di esso il segnale non funziona in tutti i casi.Traccia di assegnazione gruppo utenti in django admin

Qualcuno può suggerirmi come sovrascrivere il metodo di salvataggio utente Django e gestire il gruppo modificato in tale metodo? o in qualsiasi altro modo per tracciare l'assegnazione del gruppo di utenti?

Sto usando Django 1.6

+0

Penso che potresti mostrare del codice, in modo che altri possano capirti meglio e pubblicare una soluzione. – pktangyue

risposta

5

Questo è un problema noto di Django ed è stato risolto solo in 1.9: https://docs.djangoproject.com/en/1.9/releases/1.9/#related-set-direct-assignment.

assegnazione diretta di oggetti correlati nel ORM utilizzato per eseguire un chiaro() seguita da una chiamata a add(). Ciò ha causato modifiche inutilmente grandi ai dati e impedito l'utilizzo del segnale m2m_changed per tracciare le singole variazioni di nelle relazioni molti-a-molti.

L'assegnazione diretta ora si basa sul nuovo metodo set() sui relativi gestori che, per impostazione predefinita, modifica solo i processi tra il set relativo esistente e quello che è stato appena assegnato. Il comportamento precedente può essere ripristinato sostituendo l'assegnazione diretta con una chiamata a set() con l'argomento parola chiave clear = True.

ModelForm, e quindi ModelAdmin, internamente si basano su assegnazione diretta per molti-a-molti rapporti e di conseguenza ora utilizzare il nuovo comportamento .

Se si utilizzava manualmente user.groups.add(foo) o user.groups.remove(foo), il ricevitore di segnale corrente dovrebbe funzionare correttamente. Ma l'admin di django usa l'assegnazione in modo che sia chiaro e impostato su ogni salvataggio da django-admin. Per risolvere questo problema senza aggiornare a django 1.9, è necessario elaborare sia pre_clear sia post_add: archivio cancellato pks in un attributo "speciale" di istanza in preclear e quindi calcolare cosa è stato aggiunto o rimosso.

def pre_clear_handler(sender, *args, **kwargs): 
    # ... 
    instance._cleared_groups_pk_set = set([group.pk for group in instance.groups.all()]) # or `set(instance.groups.all().values_list('pk', flat=True)) 
    tracker = SomeTrackingModel() 
    tracker.removed_group_ids = instance._cleared_groups_pk_set 
    tracker.save() # post_add may not be called if groups are fully cleared 
    instance._changes_tracker_helper = tracker 

def post_add_handler(sender, *args, **kwargs): 
    # ... 
    prev_groups_pk_set = getattr(instance, '_cleared_groups_pk_set', None) 
    if prev_groups_pk_set is not None: 
     not_realy_added_pk_set = kwargs['pk_set'] 
     removed_pks = prev_groups_pk_set - not_realy_added_pk_set 
     realy_added_pks = not_realy_added_pk_set - prev_groups_pk_set 
    else: 
     removed_pks = set() 
     realy_added_pks = kwargs['pk_set'] 
    tracker = getattr(instance, '_changes_tracker_helper', SomeTrackingModel()) 
    tracker.removed_group_ids = removed_pks 
    tracker.added_group_ids = realy_added_pks 
    tracker.save() 
+0

Sì, ora lo sto gestendo nello stesso modo in cui hai menzionato ma quando tutti i gruppi vengono rimossi, solo pre_clear chiamato e post_add non sta chiamando, quindi come posso rilevare che tutti i gruppi sono stati rimossi usando questi segnali? Nota: per qualche motivo non posso effettuare l'aggiornamento a 1.9 ora. – Yogesh

+0

soluzione possibile per salvare le modifiche in pre_clear e tracciare "modifica oggetto" in istanza ('...; tracker.removed_group_ids = instance._cleared_groups_pk_set; tracker.save(); instance.change_tracker = tracker'). e in post_add: ripristina o modifica le modifiche tracciate per correggerne una e salvarle di nuovo ('instance.change_tracker.removed_group_ids = removed_pks; ...; instance.change_tracker.save()'. In questo modo anche pre_clear senza post_add verrà tracciato anche – imposeren

+0

aggiornato my rispondere per mostrare come gestire quando i gruppi sono completamente cancellati e/o aggiunti – imposeren