2011-01-27 18 views
5

Me pregunto si es posible suprimir selectivamente una señal de Django (como post_save o post_init) en la creación del objeto, o, como alternativa, enviarle ciertos parámetros.¿Es posible suprimir selectivamente una señal post_save (u otra) en Django?

Lo que tengo es un objeto User, que se puede crear de muchas formas y lugares en mi código. Entonces, para asignar automáticamente un objeto personalizado Profile a cada User, uso la señal post_save. Sin embargo, en un caso específico, hay información adicional que quiero vincular al objeto Profile creado. Pasarlo como argumentos a la señal post_save sería genial, pero no parece posible.

La otra opción es crear manualmente el objeto Profile, pero entonces necesito que después de la User se guarda, de lo contrario el Profile no puede estar vinculado a una instancia User. Sin embargo, al guardar la instancia User, se crea otro Profile a través de la función llamada por la señal.

Y no puedo obtener el objeto recién creado Profile, ya que da como resultado un error 'Profile' object is unsubscriptable. ¿Algún consejo?

Actualización:

Aquí es un ejemplo de una posible situación:

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() 

¿Cómo consigo la variable extra_param en el método signup al método createUserProfile, donde se va a almacenar como parte del objeto Profile?

+1

+1. Me encantaría saber la respuesta a esto. – PeanutButterJelly

Respuesta

2

¿Por qué esto no funciona para usted?

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

Si usted está obsesionado con los parámetros que pasa a caso, es posible, sino el mal:

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

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

es malo porque las personas que van a leer su código tendrán ni idea de qué diablos esos _evil_extra_args es para y como funciona.

+3

Al final opté por la opción mal, ya que la primera da algún tipo de error de concurrencia (el objeto db sigue bloqueado desde el evento 'save()' cuando intento acceder al perfil). –

0

Retrasar post_save no es posible (a menos que desee entirely disconnect it), pero tampoco es necesario. Al pasar un parámetro para el perfil no es un problema en absoluto:

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

¿Qué pasa si quiero enviar ese parámetro solo en un caso, y el 'post_save.connect' se define en algún lugar que no sea la función que crea el objeto' User' en sí? ¿Cómo funcionaría eso? –

+0

simplemente dale un valor predeterminado ... (respuesta editada) –

+0

Creo que uno de nosotros está malinterpretando al otro, así que agregué un ejemplo a mi pregunta que con suerte aclarará el problema. –

Cuestiones relacionadas