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 объясняет такое поведение ;)

Вернуться на верх