Django 信号指南
Django 信号系统让解耦的组件响应事件。学习 pre/post save、delete 信号、自定义信号和安全模式。
1. 内置模型信号
from django.db.models.signals import pre_save, post_save, post_delete
from django.dispatch import receiver
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(pre_save, sender=Article)
def auto_slug(sender, instance, **kwargs):
if not instance.slug:
from django.utils.text import slugify
instance.slug = slugify(instance.title)
@receiver(post_delete, sender=Article)
def delete_cover_image(sender, instance, **kwargs):
if instance.cover_image:
instance.cover_image.delete(save=False)
# 在 AppConfig.ready() 中注册
class MyAppConfig(AppConfig):
name = "myapp"
def ready(self):
import myapp.signals # noqa
2. 安全信号模式
from django.db import transaction
# 使用 on_commit 避免竞态条件
@receiver(post_save, sender=Order)
def notify_fulfillment(sender, instance, created, **kwargs):
if created:
transaction.on_commit(lambda: process_order.delay(instance.pk))
# 避免无限循环 — 检查 update_fields
@receiver(post_save, sender=Article)
def update_stats(sender, instance, **kwargs):
update_fields = kwargs.get("update_fields")
if update_fields is None or "status" in update_fields:
# 执行统计更新
pass
3. 自定义信号
from django.dispatch import Signal
article_published = Signal()
def publish_article(article, user):
article.status = "published"
article.save(update_fields=["status"])
article_published.send(sender=Article, article=article, publisher=user)
@receiver(article_published)
def on_article_published(sender, article, publisher, **kwargs):
Notification.objects.create(
user=article.author,
message=f'您的文章"{article.title}"已由 {publisher} 发布',
)
4. 断开信号
from django.db.models.signals import post_save
def my_handler(sender, instance, **kwargs):
print(f"已保存: {instance}")
post_save.connect(my_handler, sender=MyModel)
post_save.disconnect(my_handler, sender=MyModel)
5. 内置信号参考
| 信号 | 触发时机 |
|---|---|
| pre_save | model.save() 之前 |
| post_save | model.save() 之后 |
| pre_delete | model.delete() 之前 |
| post_delete | model.delete() 之后 |
| m2m_changed | 多对多关系变更 |
| user_logged_in | 用户登录成功 |
| request_started | HTTP 请求开始 |