Где разместить код инициализации Django?
Я хочу, чтобы следующие строки кода выполнялись при старте сервера (как в режиме разработки, так и в продакшене):
from django.core import management
management.call_command('syncdb', interactive=False)
Помещение этого кода в settings.py
не сработало, так как для его выполнения требуется, чтобы настройки уже были загружены.
Попытка разместить код в представлении и доступ к этому представлению извне также не удалась, поскольку есть некоторые промежуточные слои (middlewares), которые используют базу данных, и они выдают ошибку, тем самым не позволяя мне получить доступ к представлению.
Поместить код в промежуточное программное обеспечение (middleware) было бы возможно, но такое решение сработало бы каждый раз при обращении к приложению. Одно из возможных решений - создать промежуточное программное обеспечение, которое выполнит всю работу и затем удалит себя из MIDDLEWARE_CLASSES
, чтобы больше не вызываться. Могу ли я это сделать без значительных изменений в коде (monkey-patching)?
5 ответ(ов)
Если вы работаете с Django 1.7 и выше и хотите выполнить некоторый код при старте приложения, следуя при этом двум условиям:
1. Не выполнять его при миграциях (migrate
), создании миграций (makemigrations
), в интерактивной оболочке и т.д.
2. Избежать повторного выполнения кода
Решением будет использование следующего подхода:
Создайте файл myapp/apps.py
с содержимым:
from django.apps import AppConfig
def startup():
# Здесь размещается ваш код, который нужно выполнить при старте
class MyAppConfig(AppConfig):
name = 'myapp'
verbose_name = "Мое Приложение"
def ready(self):
import os
if os.environ.get('RUN_MAIN'):
startup()
Затем в файле myapp/__init__.py
добавьте строку для регистрации вашего класса конфигурации приложения:
default_app_config = 'myapp.apps.MyAppConfig'
Данный подход использует рекомендации от @Pykler и @bdoering.
Если вы используете Apache/mod_wsgi, вам нужно воспользоваться WSGI скриптом, описанным по следующему адресу:
http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html
Добавьте необходимые вам строки после активации языковых переводов.
Таким образом, ваш код будет выглядеть следующим образом:
import sys
sys.path.insert(0, '/usr/local/django/mysite')
import settings
import django.core.management
django.core.management.setup_environ(settings)
utility = django.core.management.ManagementUtility()
command = utility.fetch_command('runserver')
command.validate()
import django.conf
import django.utils
django.utils.translation.activate(django.conf.settings.LANGUAGE_CODE)
# Ваша строка здесь.
django.core.management.call_command('syncdb', interactive=False)
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Не забудьте заменить строку # Ваша строка здесь.
на нужную вам команду или инициализацию, которая должна выполняться после активации переводов. Примечание: в современных версиях Django используйте migrate
вместо syncdb
, так как syncdb
устарел.
Вы можете создать собственную команду и реализовать ваш код в функции handle
. Подробности можно найти здесь: документация Django.
После этого вы можете создать скрипт запуска, который сначала запустит сервер Django, а затем выполнит вашу новую пользовательскую команду.
Если вы используете mod_wsgi, вы можете поместить это в стартовую функцию вашего WSGI-приложения.
Если вы сталкиваетесь с проблемой отсутствия сигнала запуска в Django, вот как я обошёл это ограничение:
Я создал специальное приложение, основываясь на идее Росса Макафарланда. Код, который вызывается в этом приложении, специфичен для моего проекта djangosite, но сам трюк может быть применён и в других проектах.
Вы можете ознакомиться с кодом по следующей ссылке: Django site models.py.
Надеюсь, это поможет вам решить вашу проблему!
'pip' не распознан как командa внутреннего или внешнего формата
Как выполнить поиск в стиле getattr() в шаблоне Django
Инструмент для выявленияCircular Imports в Python/Django?
PIL / JPEG библиотека: "декодировщик JPEG недоступен"
"_set" в объекте queryset в Django