Ответ 1
Мне действительно нравится делать их классными методами самой модели. Это держит все в пределах одного класса и означает, что вам не нужно беспокоиться о том, чтобы импортировать что-либо.
Я только что начал внедрять прослушиватели сигналов в проекте django. Хотя я понимаю, что это такое и как их использовать. Мне сложно определить, куда я должен их поместить. В документации на сайте django есть следующее:
Вы можете поместить обработку сигнала и регистрационный код где угодно. Однако вам нужно убедиться, что модуль, который он импортирует рано так что обработка сигнала до того, как какие-либо сигналы быть отправлен. Это делает ваше приложение models.py хорошее место для размещения регистрация обработчиков сигналов.
В то время как его хорошее предложение, имея немодельные классы или методы в моих моделях .py, просто втирает меня в неправильный путь.
Итак, какова наилучшая практика/правило для хранения и регистрации обработчиков сигналов?
Мне действительно нравится делать их классными методами самой модели. Это держит все в пределах одного класса и означает, что вам не нужно беспокоиться о том, чтобы импортировать что-либо.
Это было добавлено в документацию когда был выпущен 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(), поскольку оно часто вызывает проблемы с циклическим импортом.
Я только что натолкнулся на это, и поскольку мои сигналы не связаны с моделью, я думал, что добавлю свое решение.
Я регистрирую различные данные о входе/выходе из журнала и нуждаюсь в подключении к 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), поэтому я открыт для всех, кто говорит мне, что это ужасная идея!
Недавно я прочитал статью эту статью о лучших практиках, когда дело доходит до разработки ваших проектов/приложений, и это говорит о том, что весь ваш пользовательский диспетчер сигналы должны поступать в файл с именем signals.py
. Однако это не полностью решает вашу проблему, поскольку вам все равно нужно импортировать их где-нибудь, и чем раньше они импортируются, тем лучше.
Предложение модели является хорошим. Поскольку вы уже определили все в своем файле signals.py
, оно не должно занимать больше строки в верхней части файла. Это похоже на способ размещения файла admin.py
(с определениями классов вверху и кодом для регистрации всех пользовательских классов администратора внизу), если вы определяете свои сигналы, затем подключайте их в одном файле.
Надеюсь, что это поможет! В конечном счете это сводится к тому, что вы предпочитаете.
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. Никаких беспорядков в моделях и сигналах.
Надеюсь, это даст другое решение.
Я сохраняю их в отдельном файле 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, но он более управляем таким образом.
Надеюсь, это поможет!