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()
Penso che potresti mostrare del codice, in modo che altri possano capirti meglio e pubblicare una soluzione. – pktangyue