2009-10-28 20 views
10

Estoy tratando de actualizar inmediatamente un registro después de guardarlo. Este ejemplo puede parecer inútil, pero imaginar que tenemos que utilizar una API después de los datos se guardan para obtener algo de información extra y actualizar el registro:post_save en django para actualizar la instancia inmediatamente

def my_handler(sender, instance=False, **kwargs): 
    t = Test.objects.filter(id=instance.id) 
    t.blah = 'hello' 
    t.save() 

class Test(models.Model): 
    title = models.CharField('title', max_length=200) 
    blah = models.CharField('blah', max_length=200) 

post_save.connect(my_handler, sender=Test) 

Así se supone que el campo 'extra' que se pone a 'hola' después de cada guardado. ¿Correcto? Pero no está funcionando.

¿Alguna idea?

+0

¿Quizás podría describir cómo no funciona? A primera vista, parece que sería un bucle infinito, ya que post_save llama a guardar, lo que debería invocar post_save, etc. ¿Tal vez Django está impidiendo la recursión? –

+0

Veo un bucle infinito allí. Después de t.save() se envía una señal post_save, adivine qué función se llama ... – stefanw

+0

oh, estaba bajo la impresión de que Django no permitiría que el segundo guardado activara post_save nuevamente? Supongo que no. En ese caso, tienes razón. Sería un ciclo infinito. Pero no estoy viendo el ciclo ni nada. – givp

Respuesta

18

Cuando se encuentra utilizando una señal post_save para actualizar un objeto de la clase de remitente, es probable que deba reemplazar el método de guardar. En su caso, la definición del modelo sería similar a:

class Test(models.Model): 
    title = models.CharField('title', max_length=200) 
    blah = models.CharField('blah', max_length=200) 

    def save(self, force_insert=False, force_update=False): 
     if not self.blah: 
      self.blah = 'hello' 
     super(Test, self).save(force_insert, force_update) 
+1

Si le está haciendo esto a los modelos de administrador, post_save es una mejor solución que la subclasificación de los modelos de administración existentes y la sobrescritura de guardado. –

+0

@Paul McMillan ¿por qué? –

+0

'using = False' es necesario en la lista de argumentos del método 'guardar' en Django 1.3 y superior – eviltnan

6

¿No toma la instancia el controlador post_save? ¿Por qué estás filtrando usando? ¿Por qué no acaba de hacer:

def my_handler(sender, instance=False, created, **kwargs): 
    if created: 
    instance.blah = 'hello' 
    instance.save() 

su código existente no funciona porque se realiza un bucle, y Test.objects.filter(id=instance.id) devuelve un conjunto de consultas, no un objeto. Para obtener un solo objeto directamente, use Queryset.get(). Pero no necesitas hacer eso aquí. El argumento creado evita que se repita, ya que solo lo establece la primera vez.

En general, a menos que sea absolutamente necesario usar señales de post_save, debe reemplazar el método save() de su objeto de todos modos.

+0

De hecho, también intenté en vano. pero si las personas de arriba son correctas, no puedo hacer esto de todos modos ya que simplemente se quedará atascado en un bucle post_save. – givp

+0

Pruébalo usando la marca creada. Creo que eso debería solucionar su problema, porque creado no está configurado en los siguientes bucles. –

+1

Es posible que desee consultar esta pregunta para obtener más información sobre cuándo utilizar las señales y cuándo anular el guardado: http://stackoverflow.com/questions/170337/django-signals-vs-overriding-save-method –

Cuestiones relacionadas