Django `sender` не работает для приемника сигналов
Я пытаюсь создать обработчик post_save
для сигнала, когда модель Client
была сохранена. Причина, по которой я использую сигнал, заключается в том, что мне требуется, чтобы код запускался при добавлении клиента через loaddata
также.
А вот и отправитель:
# apps.py
from django.db.models.signals import post_save
class ClientsConfig(AppConfig):
name = 'clients'
verbose_name = "clients"
def ready(self):
"""https://docs.djangoproject.com/en/4.1/topics/signals/"""
# Implicitly connect signal handlers decorated with @receiver.
from . import signals
# Explicitly connect a signal handler.
post_save.connect(signals.write_svg, dispatch_uid="clients_client_post_save")
Вот приемник:
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Client
@receiver(post_save, sender=Client)
def write_svg(sender, instance, **kwargs):
"""Using a signal so that when one loaddata the DB, it performs this action too"""
print('\n-----------------------------------------------------')
print('Signal called, sender', sender)
Здесь вы можете увидеть, что он печатает для целой кучи событий Session и многих других событий, вместо того, чтобы фильтровать только модель клиента:
-----------------------------------------------------
Signal called, sender <class 'django.contrib.sessions.models.Session'>
-----------------------------------------------------
Signal called, sender <class 'django.contrib.sessions.models.Session'>
-----------------------------------------------------
Signal called, sender <class 'django.contrib.sessions.models.Session'>
-----------------------------------------------------
Signal called, sender <class 'django.contrib.sessions.models.Session'>
-----------------------------------------------------
Signal called, sender <class 'django.contrib.sessions.models.Session'>
Проблема в том, что сигнал регистрируется дважды. Если вы используете декоратор @receiver
, то строка:
from . import signals
автоматически подключит сигнал, вам не нужно явно его регистрировать. Второй раз он был зарегистрирован с помощью строки:
post_save.connect(signals.write_svg, dispatch_uid="clients_client_post_save")
Который не имеет фильтра sender
.
Вы должны удалить
post_save.connect(signals.write_svg, dispatch_uid="clients_client_post_save")
Вы уже использовали декоратор receivers, вам не нужно использовать и функцию connect.
Первый комментарий к вашему методу ready объясняет такое поведение ;)