正确的理解和使用Django信号(Signals)
django 提供一个了“信号分发器”机制,允许解耦的应用在框架的其它地方发生操作时会被通知到。 通俗而讲django信号的工作原理就是当某个事件发生的时候会发出一个信号(signals), 而监听这个信号的函数(receivers)就会立即执行。django信号的应用场景很多,尤其是用于不同模型或程序间的联动。常见例子包括创建user对象实例时创建一对一关系的userprofile对象实例,或者每当用户下订单时触发给管理员发邮件的动作。今天小编我就分享下如何正确使用django的信号(signals)。
django信号的一个简单例子
假设我们有一个如下user模型,我们希望每次有user对象新创建时都打印出有新用户注册的提示信息,我们可以使用django信号(signals)轻松实现。我们的信号发送者sender是user模型,每当user模型执行post_save动作时就会发出信号。此时我们自定义的create_user函数一旦监听到user发出的post_save信号就会执行,先通过if created判断对象是新创建的还是被更新的;如果对象是新创建的,就会打印出提示信息。
# models.py
from django.db import models from django.db.models import signals from django.dispatch import receiver class user(models.model): name = models.charfield(max_length=16) gender = models.charfield(max_length=32, blank=true) def create_user(sender, instance, created, **kwargs): if created: print("new user created!") post_save.connect(create_user, sender=user)
在上例中我们使用了信号(post_save)自带的connect的方法将自定义的函数与信号发出者(sender)user模型进行了连接。在实际应用中一个更常用的方式是使用@receiver装饰器实现发送者与监听函数的连接,如下所示。@receiver(post_save, sender=user)读起来的意思就是监听user模型发出的post_save信号。
from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver class user(models.model): name = models.charfield(max_length=16) gender = models.charfield(max_length=32, blank=true) @receiver(post_save, sender=user) def create_user(sender, instance, created, **kwargs): if created: print("new user created!")
利用django信号实现不同模型的联动更新
我们再来看一个复杂一点的例子。我们有一个profile模型,与user模型是一对一的关系。我们希望创建user对象实例时也创建profile对象实例,而使用post_save更新user对象时不创建新的profile对象。这时我们就可以自定义create_user_profile和save_user_profile两个监听函数,同时监听sender(user模型)发出的post_save信号。由于post_save可同时用于模型的创建和更新,我们用if created这个判断来加以区别。
from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver class profile(models.model): user = models.onetoonefield(user, on_delete=models.cascade) birth_date = models.datefield(null=true, blank=true) @receiver(post_save, sender=user) def create_user_profile(sender, instance, created, **kwargs): if created: profile.objects.create(user=instance) @receiver(post_save, sender=user) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
django常用内置信号
之前的例子中我们使用的都是post_save信号,即在模型调用save()方法后才发送信号。django其它常用内置信号还包括:
- django.db.models.signals.pre_save & post_save在模型调用 save()方法之前或之后发送。
- django.db.models.signals.pre_init& post_init在模型调用_init_方法之前或之后发送。
- django.db.models.signals.pre_delete & post_delete在模型调用delete()方法或查询集调用delete() 方法之前或之后发送。
- django.db.models.signals.m2m_changed在模型多对多关系改变后发送。
- django.core.signals.request_started & request_finished django建立或关闭http 请求时发送。
如何正确放置django信号的监听函数代码
在之前案例中,我们将django信号的监听函数写在了models.py文件里。当一个app的与信号相关的自定义监听函数很多时,此时models.py代码将变得非常臃肿。一个更好的方式把所以自定义的信号监听函数集中放在app对应文件夹下的signals.py文件里,便于后期集中维护。
假如我们有个account的app,包含了user和pofile模型,我们不仅需要在account文件夹下新建signals.py,还需要修改account文件下apps.py和__init__.py,以导入创建的信号监听函数。
# account/signals.py
from django.db.models.signals import post_save from django.dispatch import receiver from .models import user, profile @receiver(post_save, sender=user) def create_user_profile(sender, instance, created, **kwargs): if created: profile.objects.create(user=instance) @receiver(post_save, sender=user) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
# account/apps.py
from django.apps import appconfig class accountconfig(appconfig): name = 'account' def ready(self): import account.signals
# account/__init__.py
default_app_config = 'account.apps.accountconfig'
小结
在本文里我们总结了django信号(signals)的工作原理,介绍了如何使用django信号实现模型或程序的联动。最后我们还总结了django常用内置信号以及如何正确放置自定义的信号监听函数。欢迎关注我们更多python web开发和django原创文章。
以上就是正确的理解和使用django信号(signals)的详细内容,更多关于django信号(signals)的资料请关注其它相关文章!