Passer des arguments signaux django - post save / pre save
je travaille sur une application de notification dans Django 1.6 et je veux passer des arguments supplémentaires aux signaux Django tels que post_save
. J'ai essayé d'utiliser partielle de functools mais pas de chance.
from functools import partial
post_save.connect(
receiver=partial(notify,
fragment_name="categories_index"),
sender=nt.get_model(),
dispatch_uid=nt.sender
)
notify
est la fonction d'un argument mot-clé fragment_name
que je veux passer par défaut dans mes signaux.
des suggestions?
4 réponses
votre tentative avec partial ne fonctionne pas parce que par défaut ces récepteurs sont connectés en utilisant une référence faible.
Selon Django docs:
Django magasins les gestionnaires de signaux faibles références par défaut, donc si votre gestionnaire est une fonction locale, il peut être nettoyée. Pour éviter cela, pass weak=False quand vous appelez connect () du signal.
from functools import partial
post_save.connect(
receiver=partial(notify,
fragment_name="categories_index"),
sender=nt.get_model(),
dispatch_uid=nt.sender,
weak=False
)
sont la faiblesse de l'=Faux et cela partielle ne sera pas les ordures collectées.
ma réponse originale est ci-dessous et a pris une approche qui n'était pas partielle.
vous pouvez décorer votre fonction Post save avant de la connecter avec le récepteur post_save.
from django.dispatch import receiver
from django.db.models.signals import pre_save, post_save, post_delete
def extra_args(fragment_name, *args, **kwargs):
def inner1(f, *args, **kwargs):
def inner2(sender, instance, **kwargs):
f(sender, instance, fragment_name=fragment_name, **kwargs)
return inner2
return inner1
@receiver(post_save, sender=ExampleModel)
@extra_args(fragment_name="categories_index")
def my_post_save(sender, instance, fragment_name, **kwargs):
print "fragment_name : ", fragment_name
#rest of post save...
Le extra intérieure en extra_args est pour décorateurs qui prennent des paramètres.
Si vous voulez le faire par programmation cela fonctionne de la même manière, mais notez que vous devez inclure weak=False
pour avoir la enveloppé fonction pas les ordures collectées.
receiver(post_save, sender=aSenderClass, weak=False)(extra_args(fragment_name="meep")(my_post_save))
Ou sans emballage, mais en l'appelant post_save.connectez - vous comme votre première tentative avec
post_save.connect(extra_args(fragment_name="meepConnect")(my_post_save), sender=Author, weak=False)
vous pouvez définir des arguments supplémentaires dans la méthode de sauvegarde personnalisée de model comme ceci:
class MyModel(models.Model):
....
def save(self, *args, **kwargs):
super(MyModel, self).save(*args, **kwargs)
self.my_extra_param = 'hello world'
et accéder à cet argument supplémentaire par l'intermédiaire de l'instance dans le récepteur de signal post_save:
@receiver(post_save, sender=MyModel)
def process_my_param(sender, instance, *args, **kwargs):
my_extra_param = instance.my_extra_param
si les signaux prédéfinis ne conviennent pas, vous pouvez toujours définir les vôtres.
import django.dispatch
custom_post_save = django.dispatch.Signal(providing_args=[
"sender", "instance", "created", "raw", "using", "update_fields", "fragment_name"
])
alors dans votre Model vous avez juste à outrepasser save()
méthode:
from django.db import router
class YourModel(Model):
# Your fields and methods
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
custom_signal_kwargs = {
"sender": self.__class__,
"instance": self,
"created": self.pk is None,
"raw": False, # As docs say, it's True only for fixture loading
"using": using or router.db_for_write(self.__class__, instance=self),
"update_fields": update_fields,
"fragment_name": "categories_index" # The thing you want
}
super(YourModel, self).save(force_insert=False, force_update=False, using=None,
update_fields=None)
custom_post_save.send(**custom_signal_kwargs) # Send custom signal
Maintenant, vous avez juste à connecter ce signal personnalisé pour votre notify(...)
récepteur et il obtiendra fragment_name
en kwargs.
le code en Django responsable des signaux est défini ici https://github.com/django/django/blob/master/django/dispatch/dispatcher.py