Django pre_save signal does not work

江枫思渺然 提交于 2019-12-22 04:04:55

问题


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)
  1. 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.

  2. 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.

  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!