Отправка и получение сигналов в моделях Django - PullRequest
0 голосов
/ 31 августа 2018

Я использую django 2.0.8 и Python 3.5. Я хочу иметь возможность отправлять и получать пользовательские сигналы, когда объект сохраняется в базе данных.

Я следовал документации Django по прослушиванию сигналов , а также основных сигналов в комплекте с Django - однако я не могу заставить мой пример работать.

Это то, что я имею до сих пор:

MyApp / models.py

from django.db import models
import django.dispatch

my_signal = django.dispatch.Signal(providing_args=["name"])

class Foo(models.Model):
    name = models.CharField(max_length=16)

def save(self, *args, **kwargs):
    try:
        # Call the "real" save() method.
        super().save(*args, **kwargs)  

        # Fire off signal         
        my_signal.send(sender=self.__class__, name=self.name)

    except Exception as e:
        print ('Exception:', e)
        #pass

MyApp / signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print('Foo Signal Recieved!')
    print(kwargs)

MyApp / app.py

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

Пример использования

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save() # Object is saved, but event is not fired!

Может кто-нибудь объяснить, почему сигнал не срабатывает?

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018
  1. В myapp.signals у вас есть приемник, который обрабатывает сигнал post_save (@receiver(post_save, sender=Foo)), который не подключается к вашему сигналу.
  2. Убедитесь, что вы используете конфигурацию своего приложения в __ init __. Py вашего приложения default_app_config = 'myapp.apps.MyappConfig'
  3. Чтобы подключиться к созданному вами сигналу, попробуйте это в своем файле signal.py:

    @receiver(my_signal)
        def my_handler(name, **kwargs):
            print(name)
    
0 голосов
/ 09 сентября 2018

Вы заново изобретаете колесо, но кладете его только на одну сторону тележки, так сказать.

сигнал post_save всегда отправляется при сохранении, поэтому определение вашего собственного сигнала является излишним. Я знаю, что у вас есть аргумент там, но у получателя уже есть аргумент sender, который является сохраненным объектом, так что вы можете просто сделать sender.name и вы получите нужное значение.

Кроме того, у вас есть синтаксическая ошибка, ваша пользовательская функция сохранения для вашей модели не имеет отступа. Я не знаю, является ли это ошибкой форматирования в вашем вопросе или так выглядит в вашем коде. В любом случае, должно работать, если вы просто сбросите свой сигнал.

Модель

from django.db import models
import django.dispatch


class Foo(models.Model):
    name = models.CharField(max_length=16)

Сигналы

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print(sender.name)

App

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

Пример

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save()
0 голосов
/ 04 сентября 2018

Кажется, вам нужны две функции, предоставляемые Django. сигнал и contenttypes .

Итак, сначала прочтите документ

Модель Активность связана с contenttypes , кажется, вы пропустили поле object_id, которое указывает, какой экземпляр модели используется.

Для каждого грубого действия создается экземпляр Activity . Эта часть является просто кодом, написанным в signal.py

сигнал : сигнал должен подключить каждую конкретную модель. К счастью, см. Исходный код декоратора приемника .

У нас есть список сигналов [post_save, post_delete] и список моделей (FoodooChile, FooBarChile) для подключения.

В post_save аргумент созданный указывает, что действие создано или обновлено.

Наконец, обычно мы импортируем файл сигнала в urls.py, возможно, это не лучшая практика.


Это также относится к вашему settings.py. использовать 'myapp.apps.MyappConfig' заменить myapp в settings.py, или определить default_app_config = 'myapp.apps.MyappConfig' в myapp/__init__.py. Ссылка выше в комментариях подробно описывает это

...