问题
I tested the "pre_save" signal of Django in the following ways, but cannot catch the signal in either of them.
$
from django.db.models.signals import pre_save
import logging
def my_callback(sender, **kwargs):
logging.debug("======================================")
pre_save.connect(my_callback)
Run the above code in manage.py shell: Then I run my website and see models.save() work successfully, but the callback function does not run.
Alternatively, I run the above code on shell again and then run models.save() in the shell. "save" works well again but still nothing happens to the callback function.
Finally, I embed the above code in an
__init__.py
file and still, run the save() function on the website. Still, nothing occurs.
Would you please help me figure out why pre_save signal seems not work?
回答1:
You're not setting the sender class for one.
from django.db.models.signals import pre_save
from myapp.models import MyModel
import logging
def my_callback(sender, **kwargs):
logging.debug("======================================")
pre_save.connect(my_callback, sender=MyModel)
Secondly, if you're using Django 1.3 you should use the new decorator syntax.
# Inside your models.py
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
class MyModel(models.Model):
field1 = models.TextField()
field2 = models.IntegerField()
@receiver(pre_save, sender=MyModel)
def mymodel_save_handler(sender, **kwargs):
logging.debug("======================================")
That should do it, but I haven't tested the code so let me know if it's still broken.
回答2:
The reason Eric's answer made it work is because he got you to connect the signal inside models.py, so that when you then save the model via your website the signal handler is in the same process as the signal firer.
In examples 1 and 3 it's easy to see why they didn't work - you are saving in a different process (the website) to where your signal receivers are listening.
I wish I understood better why example 2 is also broken but I just debugged a similar issue in my own project while testing signals in the shell and it's definitely something to do with signal senders and receivers not being able to 'see' each other.
回答3:
logging.debug()
is using the root logger, which handler level by default is 30 ('WARNING').
=> logging.debug('something')
is just not doing anything at all (DEBUG level is 10 < 30). See http://docs.python.org/2/library/logging.html
The same test should be done with another custom logger, or by doing:
l = logging.getLogger()
l.setLevel(10)
def my_callback(sender, **kwargs):
logging.debug("======================================")
pre_save.connect(my_callback)
The original question is not containing enough info to know if it's the real problem the OP was facing (or part of it).
But surely the OP's code was not going to work with my ./manage.py shell
回答4:
as described in the django signals doc the pre_save
signal accept 3 unique arguments (not keyword arguments) so, you need to edit your my_callback
function to be as follow:
def my_callback(sender,instance, using, **kwargs):
logging.debug("======================================")
来源:https://stackoverflow.com/questions/6153730/django-pre-save-signal-does-not-work