Подтвердить что ты не робот

Где должны быть обработчики сигналов в проекте django?

Я только что начал внедрять прослушиватели сигналов в проекте django. Хотя я понимаю, что это такое и как их использовать. Мне сложно определить, куда я должен их поместить. В документации на сайте django есть следующее:

Где должен жить этот код?

Вы можете поместить обработку сигнала и регистрационный код где угодно. Однако вам нужно убедиться, что модуль, который он импортирует рано так что обработка сигнала до того, как какие-либо сигналы быть отправлен. Это делает ваше приложение models.py хорошее место для размещения регистрация обработчиков сигналов.

В то время как его хорошее предложение, имея немодельные классы или методы в моих моделях .py, просто втирает меня в неправильный путь.

Итак, какова наилучшая практика/правило для хранения и регистрации обработчиков сигналов?

4b9b3361

Ответ 1

Мне действительно нравится делать их классными методами самой модели. Это держит все в пределах одного класса и означает, что вам не нужно беспокоиться о том, чтобы импортировать что-либо.

Ответ 2

Это было добавлено в документацию когда был выпущен Django 1.7:

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

На практике обработчики сигналов обычно определяются в сигнальном подмодуле приложения, к которому они относятся. Сигнальные приемники подключены в режиме ready() вашего класса конфигурации приложения. Если вы используете декодер получателя(), просто импортируйте подмодуль сигналов внутри ready().

Изменено в Django 1.7: Поскольку ready() не существовало в предыдущих версиях Django, регистрация сигналов обычно происходила в модуле моделей.

Лучшей практикой является определение ваших обработчиков в handlers.py в подмодуле сигналов, например. файл, который выглядит следующим образом:

YourApp/сигналы/handlers.py:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    pass

Лучшее место для регистрации вашего обработчика сигнала затем находится в AppConfig приложения, которое его определяет, используя метод ready(). Это будет выглядеть так:

YourApp/apps.py:

from django.apps import AppConfig

class TasksConfig(AppConfig):
    name = 'tasks'
    verbose_name = "Tasks"

    def ready(self):
        import yourproject.yourapp.signals.handlers #noqa

Убедитесь, что вы загружаете AppConfig, указав его либо непосредственно в настройках .py INSTALLED_APPS, либо в __init__ вашего приложения. Для получения дополнительной информации см. документацию ready().

Примечание. Если вы также предоставляете сигналы другим приложениям для прослушивания, поместите их в __init__ в ваш модуль сигналов, например. файл, который выглядит следующим образом:

YourApp/сигналы/__ __ INIT. Ру

import django.dispatch

task_generate_pre_save = django.dispatch.Signal(providing_args=["task"])

Другое приложение может затем прослушать ваш сигнал, импортировав его и зарегистрировав его, например. from yourapp.signals import task_generate_pre_save. Разделение ваших сигналов с ваших обработчиков сохраняет чистоту.

Инструкции для Django 1.6:

Если вы все еще застряли на Django 1.6 или ниже, то вы сделаете то же самое (определите своих обработчиков в yourapp/signals/handlers.py), но вместо использования AppConfig вы загрузите обработчики через __init__.py вашего приложения, например что-то вроде:

YourApp/__ __ INIT. Ру

import signals

Это не так хорошо, как использование метода ready(), поскольку оно часто вызывает проблемы с циклическим импортом.

Ответ 3

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

Я регистрирую различные данные о входе/выходе из журнала и нуждаюсь в подключении к django.contrib.auth.signals.

Я поместил обработчики сигналов в файл signals.py, а затем импортировал сигналы из файла модуля __init__.py, так как я считаю, что это вызвано, как только приложение запустится (тестирование с помощью инструкции print который он вызывал еще до чтения файла настроек.)

# /project/__init__.py
import signals

и в signal.py

# /project/signals.py
from django.contrib.auth.signals import user_logged_in

def on_logged_in(sender, user, request, **kwargs):
    print 'User logged in as: \'{0}\''.format(user)

user_logged_in.connect(on_logged_in)

Я новичок в Django (/python), поэтому я открыт для всех, кто говорит мне, что это ужасная идея!

Ответ 4

Недавно я прочитал статью эту статью о лучших практиках, когда дело доходит до разработки ваших проектов/приложений, и это говорит о том, что весь ваш пользовательский диспетчер сигналы должны поступать в файл с именем signals.py. Однако это не полностью решает вашу проблему, поскольку вам все равно нужно импортировать их где-нибудь, и чем раньше они импортируются, тем лучше.

Предложение модели является хорошим. Поскольку вы уже определили все в своем файле signals.py, оно не должно занимать больше строки в верхней части файла. Это похоже на способ размещения файла admin.py (с определениями классов вверху и кодом для регистрации всех пользовательских классов администратора внизу), если вы определяете свои сигналы, затем подключайте их в одном файле.

Надеюсь, что это поможет! В конечном счете это сводится к тому, что вы предпочитаете.

Ответ 5

models.py и signals.py в каждом приложении были рекомендуемыми местами для подключения сигналов, однако они не являются лучшим решением, на мой взгляд, для отправки сигналов и обработчиков. Диспайкинг должен быть причиной сигналов и обработчиков, изобретенных в джанго.

Я долго боролся, и, наконец, мы выяснили решение.

создать модуль соединителя в папке приложения

поэтому имеем:

app/
    __init__.py
    signals.py
    models.py
    connectors.py

в app/connector.py, мы определили обработчики сигналов и соединим их. Приведен пример:

from signals import example_signal
from models import ExampleModel
from django.db.models.signals import post_save, post_delete

def hanndler(sender, *args, **kwargs):
    pass

post_save.connect(hander, sender=ExampleModel)

то в models.py добавим следующую строку в конец файла:

from app import connector

Все сделано здесь.

Таким образом, мы можем помещать сигналы в сигналы .py и все обработчики в connector.py. Никаких беспорядков в моделях и сигналах.

Надеюсь, это даст другое решение.

Ответ 6

Я сохраняю их в отдельном файле signals.py, In models.py после определения всех моделей. Я импортирую их и подключаю модели к сигналам.

signals.py

#  necessary imports

def send_mail_on_save(<args>):
    # code here 

models.py

# imports
class mymodel(models.Model):
    # model here

# import signals
from signals import send_mail_on_save
# connect them 
post_save.connect(send_mail_on_save,sender=mymodel)

Это дает мне логическое разделение, конечно, нет ничего плохого в том, чтобы держать их в models.py, но он более управляем таким образом.

Надеюсь, это поможет!