2014-10-21 5 views
7

Non ho molta familiarità con i segnali di Django e potrei usare un po 'di aiuto.Utilizzo di m2m_changed di Django per modificare ciò che viene salvato pre_add

Come si modifica il pk_set prima che l'istanza venga salvata? Devo restituire qualcosa al chiamante del segnale (come lo kwargs)? Oppure posso salvare lo instance da solo?

Come esempio semplificato: volevo garantire che la Categoria con pk=1 sia inclusa in tutti i miei video quando vengono salvati. Come dovrei farlo con m2m_changed?

class Video(models.Model): 
    category = models.ManyToManyField('Category') 

def video_category_changed(sender, **kwargs): 
    action = kwargs.pop('action', None) 
    pk_set = kwargs.pop('pk_set', None) 
    instance = kwargs.pop('instance', None) 

    if action == "pre_add": 
     if 1 not in pk_set: 
      pk_set.update([ 1 ]) # adding this to the set 
      # do something else? 
      # profit? 

m2m_changed.connect(video_category_changed, sender=Video.category.through) 
+1

Non è necessario restituire valori nei segnali. Inoltre, non è necessario salvare l'istanza. Basta aggiungere il codice da eseguire in risposta agli eventi selezionati. – mvillaress

risposta

16

È sufficiente aggiornare lo pk_set. Non hai bisogno di fare altro lavoro. Una volta salvata l'istanza del video, avrà una categoria con pk = 1.

from django.db import models 
from django.db.models.signals import m2m_changed 
from django.dispatch import receiver 

class Category(models.Model): 
    pass 

class Video(models.Model): 
    category = models.ManyToManyField('Category') 

@receiver(m2m_changed, sender=Video.category.through) 
def video_category_changed(sender, **kwargs): 
    action = kwargs.pop('action', None) 
    pk_set = kwargs.pop('pk_set', None)  
    if action == "pre_add": 
     if 1 not in pk_set: 
      pk_set.update([1]) 

Nel metodo precedente, le categorie verranno salvate solo dopo il salvataggio dell'istanza video. Se vuoi ESPLICITAMENTE salvarli nell'istanza m2m_changed, puoi farlo anche nel modo seguente.

@receiver(m2m_changed, sender=Video.category.through) 
def video_category_changed(sender, **kwargs): 
    instance = kwargs.pop('instance', None) 
    pk_set = kwargs.pop('pk_set', None) 
    action = kwargs.pop('action', None) 
    if action == "pre_add": 
     if 1 not in pk_set: 
      c = Category.objects.get(pk=1) 
      instance.category.add(c) 
      instance.save() 
+1

A volte le piccole cose ti bloccano - non avevo un oggetto di categoria 'pk = 1' quando stavo testando questo ... quindi, quando non funzionava, supponevo che mi mancasse qualcosa con il segnale è la prima volta che ho lavorato con quelli ... quando in realtà ero solo sciocco e avevo proprio il diritto di cominciare. Grazie per la risposta molto chiara con l'esempio. Azzeccato. – thornomad

+0

Utile, tuttavia mi sembra di dover spingere il salvataggio due volte perché abbia un effetto ... – Ycon