Я пишу класс промежуточного программного обеспечения Django, который хочу запускать только один раз при запуске, чтобы инициализировать некоторый другой произвольный код. Я следовал очень хорошему решению, опубликованному здесь sdolan , но сообщение «Hello» выводится на терминал дважды . Например
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
print "Hello world"
raise MiddlewareNotUsed('Startup complete')
и в моем файле настроек Django у меня есть класс, включенный в MIDDLEWARE_CLASSES
список.
Но когда я запускаю Django с помощью runserver и запрашиваю страницу, я попадаю в терминал
Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET / HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0
Есть идеи, почему «Hello world» печатается дважды? Спасибо.
Ответы:
Обновление от ответа Пиклера ниже: Django 1.7 теперь имеет крючок для этого
Не делай так.
Вы не хотите «промежуточное программное обеспечение» для единовременного запуска.
Вы хотите выполнить код на верхнем уровне
urls.py
. Этот модуль импортируется и выполняется один раз.urls.py
источник
Обновление: Django 1.7 теперь имеет крючок для этого
файл:
myapp/apps.py
файл:
myapp/__init__.py
Для Джанго <1,7
Ответ номер один больше не работает, urls.py загружается при первом запросе.
Что работало в последнее время, так это вставка кода запуска в любой из ваших INSTALLED_APPS init .py, например
myapp/__init__.py
При использовании
./manage.py runserver
... это выполняется дважды, но это потому, что у runserver есть некоторые хитрости для проверки моделей в первую очередь и т. Д. ... при нормальном развертывании или даже при автоматической перезагрузке runserver это выполняется только один раз.источник
На этот вопрос хорошо ответили в сообщении в блоге Хук точки входа для проектов Django , который будет работать для Django> = 1.4.
По сути, вы можете использовать
<project>/wsgi.py
это, и он будет запущен только один раз, при запуске сервера, но не при запуске команд или импорте определенного модуля.источник
Если это поможет кому - то, в дополнение к pykler в ответ, «--noreload» опция предотвращает runserver от выполнения команды на старте дважды:
Но эта команда не будет перезагружать runserver после других изменений кода.
источник
os.environ.get('RUN_MAIN')
только выполнить свой код один раз в главном процессе (см stackoverflow.com/a/28504072 )ready(self)
вызовы, но при этом мог запускать их только один раз. Ура!runserver
По умолчанию Django запускает два процесса с разными номерами pid.--noreload
заставляет это начать один процесс.Как предлагает @Pykler, в Django 1.7+ вы должны использовать ловушку, объясненную в его ответе, но если вы хотите, чтобы ваша функция вызывалась только при вызове run server (а не при вызове миграций, миграции, оболочки и т. Д. ), и вы хотите избежать исключений AppRegistryNotReady, которые вы должны сделать следующим образом:
файл:
myapp/apps.py
источник
Обратите внимание, что вы не можете надежно подключиться к базе данных или взаимодействовать с моделями внутри
AppConfig.ready
функции (см. Предупреждение в документации).Если вам нужно взаимодействовать с базой данных в вашем коде запуска, одна из возможностей - использовать
connection_created
сигнал для выполнения кода инициализации при подключении к базе данных.Очевидно, что это решение предназначено для запуска кода один раз для подключения к базе данных, а не один раз для начала проекта. Поэтому вам нужно разумное значение
CONN_MAX_AGE
параметра, чтобы не повторять код инициализации при каждом запросе. Также обратите внимание, что сервер разработки игнорируетCONN_MAX_AGE
, поэтому вы будете запускать код один раз для каждого запроса в разработке.В 99% случаев это плохая идея - код инициализации базы данных должен идти в процессе миграции, но есть некоторые случаи использования, когда вы не можете избежать поздней инициализации, и приведенные выше предостережения являются приемлемыми.
источник
my_receiver
функцию отключиться отconnection_created
сигнала, в частности, добавить следующее кmy_receiver
функции:connection_created.disconnect(my_receiver)
.если вы хотите печатать «hello world» один раз при запуске сервера, поместите print («hello world») из класса StartupMiddleware
источник