2014-10-21 11 views
7

Nie bardzo znam sygnały Django i mogę skorzystać z pomocy.Używanie Django m2m_changed do modyfikowania tego, co jest zapisywane pre_add

Jak zmodyfikować zestaw pk_set przed zapisaniem instancji? Czy muszę zwrócić coś do osoby dzwoniącej (np. kwargs)? Czy mogę samodzielnie zapisać instance?

Jako uproszczony przykład: chciałem upewnić się, że kategoria zawierająca pk=1 jest dołączona do wszystkich moich filmów wideo po ich zapisaniu. Jak to zrobić z 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

Nie jest wymagane zwracanie wartości w sygnałach. Nie musisz też zapisywać instancji. Po prostu dodaj kod do wykonania w odpowiedzi na wybrane zdarzenia. – mvillaress

Odpowiedz

16

Wystarczy aktualizacja pk_set. Nie musisz wykonywać żadnej dodatkowej pracy. Po zapisaniu instancji wideo będzie miała kategorię z 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]) 

W powyższej metodzie kategorie zostaną zapisane dopiero po zapisaniu instancji wideo. Jeśli chcesz WYGLĄDNIE zapisać je w instancji m2m_changed, możesz to zrobić w następujący sposób.

@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

To zabawne, jak małe rzeczy czasem Cię krępują - nie miałem obiektu kategorii "pk = 1", kiedy testowałem to ... więc, kiedy to nie zadziałało, założyłem, że przegapiłem coś z sygnałem odkąd to był pierwszy raz, kiedy pracowałem z tymi ... kiedy w rzeczywistości byłem po prostu głupi i miałem rację. Dzięki za bardzo jasną odpowiedź z przykładem. Przybili to. – thornomad

+0

Pomocne, ale wydaje mi się, że muszę dwukrotnie naciskać, aby mieć wpływ ... – Ycon

Powiązane problemy