2011-01-27 35 views
5

Zastanawiam się, czy można selektywnie wyłączyć sygnał Django (np. post_save lub post_init) podczas tworzenia obiektu lub, alternatywnie, przesłać mu określone parametry.Czy można selektywnie wyłączyć sygnał post_save (lub inny) w Django?

Mam obiekt User, który można utworzyć na wiele różnych sposobów i miejsc w moim kodzie. Aby automatycznie przypisać niestandardowy obiekt Profile do każdego User, używam sygnału post_save. Jednak w jednym konkretnym przypadku istnieją dodatkowe informacje, które chcę powiązać z utworzonym obiektem Profile. Podanie go jako argumentu do sygnału post_save byłoby wspaniałe, ale nie wygląda to na możliwe.

Inną opcją jest ręczne utworzenie obiektu Profile, lecz następnie trzeba aby po User jest zapisany, w przeciwnym razie Profile nie może być związana z przykładu User. Zapisanie instancji User powoduje jednak utworzenie kolejnego Profile za pośrednictwem funkcji wywoływanej przez sygnał.

I nie mogę po prostu uzyskać właśnie utworzonego obiektu Profile, ponieważ powoduje to błąd 'Profile' object is unsubscriptable. Jakakolwiek rada?

Aktualizacja:

Oto przykład możliwej sytuacji:

def createUserProfile(sender, instance, created, **kwargs): 
if created: 
    profile, created = Profile.objects.get_or_create(user=instance) 
    if extra_param: 
     profile.extra_param = extra_param 
    profile.save() 

post_save.connect(createUserProfile, sender=User) 

def signup(request): 
    ... 
    extra_param = 'param' 
    user.save() 

Jak uzyskać zmiennej extra_param w metodzie do metody createUserProfile, gdzie ma być zapisany signup jako część obiektu Profile?

+1

+1. Chciałbym poznać odpowiedź na to pytanie. – PeanutButterJelly

Odpowiedz

2

Dlaczego to nie działa?

user = User(...) 
user.save() 
# profile has been created transparently by post_save event 
profile = user.profile 
profile.extra_stuff = '...' 
profile.save() 

Jeśli obsesją parametry przechodząc do wydarzenia, możliwe, ale zła:

user = User() 
user._evil_extra_args = { ... } 
user.save() 

In event: 
extra_args = getattr(user, '_evil_extra_args', False) 

Jest zła, bo ludzie, którzy będą czytać kod nie będzie miał pojęcia, co do cholery te _evil_extra_args jest i jak to działa.

+3

Poszedłem z opcją zła na końcu, ponieważ pierwsza z nich daje pewien rodzaj błędu współbieżności (obiekt db jest nadal zablokowany przed zdarzeniem 'save()', gdy próbuję uzyskać dostęp do profil). –

0

Opóźnianie post_save nie jest możliwe (chyba że chcesz entirely disconnect it), ale nie jest to konieczne. Przekazanie parametru do profilu nie stanowi problemu:

class UserProfile(models.Model): 
    user = models.ForeignKey(User) 
    other = models.SomeField() 

def create_user_profile(sender, instance, created, other_param=None, **kwargs): 
    if created: 
     profile, created = UserProfile.objects.get_or_create(user=instance) 
     profile.other(other_param) # or whatever 
     profile.save() 

post_save.connect(create_user_profile, sender=User, other_param=p) 
+0

Co jeśli chcę wysłać ten parametr tylko w jednym przypadku, a 'post_save.connect' jest zdefiniowane gdzieś poza funkcją tworzącą obiekt' User' sam? Jak by to działało? –

+0

wystarczy podać domyślną wartość ... (edytowana odpowiedź) –

+0

Myślę, że jedno z nas nie rozumie drugiego, więc dodałem przykład do mojego pytania, które, mam nadzieję, wyjaśni problem. –

Powiązane problemy