Приложения
Django содержит реестр установленных приложений, который хранит конфигурацию и предоставляет интроспекцию. Он также поддерживает список доступных моделей.
Этот реестр называется apps, и он доступен в django.apps:
>>> from django.apps import apps
>>> apps.get_app_config('admin').verbose_name
'Administration'
Проекты и приложения
Термин проект описывает веб-приложение Django. Пакет проекта Python определяется в основном модулем настроек, но обычно содержит и другие элементы. Например, при запуске django-admin startproject mysite вы получите каталог проекта mysite, который содержит пакет Python mysite с settings.py, urls.py, asgi.py и wsgi.py. Пакет проекта часто расширяется, чтобы включать такие вещи, как фикстуры, CSS и шаблоны, которые не привязаны к конкретному приложению.
Корневой каталог проекта (тот, который содержит manage.py) обычно является контейнером для всех приложений проекта, которые не установлены отдельно.
Термин приложение описывает пакет Python, который предоставляет набор функций. Приложения могут быть повторно использованы в различных проектах.
Приложения включают некоторую комбинацию моделей, представлений, шаблонов, тегов шаблонов, статических файлов, URL-адресов, middleware и т. д. Они обычно подключаются к проектам с помощью настройки INSTALLED_APPS и необязательно с помощью других механизмов, таких как URLconfs, настройки MIDDLEWARE или наследования шаблонов.
Важно понимать, что приложение Django — это набор кода, который взаимодействует с различными частями фреймворка. Нет такого объекта, как Application. Однако есть несколько мест, где Django должен взаимодействовать с установленными приложениями, главным образом для конфигурации и интроспекции. Именно поэтому реестр приложений хранит метаданные в экземпляре AppConfig для каждого установленного приложения.
Нет ограничений на то, что пакет проекта не может также рассматриваться как приложение и иметь модели и т. д. (что потребовало бы добавления его в INSTALLED_APPS).
Настройка приложений
Для настройки приложения создайте модуль apps.py внутри приложения, затем определите подкласс AppConfig в нём.
Когда INSTALLED_APPS содержит полное имя модуля приложения, по умолчанию, если Django находит ровно один подкласс AppConfig в подмодуле apps.py, он использует эту конфигурацию для приложения. Это поведение можно отключить, установив AppConfig.default в False.
Если подмодуль apps.py содержит более одного подкласса AppConfig, Django будет искать единственный, где AppConfig.default равно True.
Если подкласс AppConfig не найден, будет использоваться базовый класс AppConfig.
В качестве альтернативы, INSTALLED_APPS может содержать полное имя конфигурации класса, чтобы указать его явно:
INSTALLED_APPS = [
...
'polls.apps.PollsAppConfig',
...
]
Для авторов приложений
# rock_n_roll/apps.py
from django.apps import AppConfig
class RockNRollConfig(AppConfig):
name = 'rock_n_roll'
verbose_name = "Rock ’n’ roll"
RockNRollConfig будет загружен автоматически, когда INSTALLED_APPS содержит 'rock_n_roll'. Если вам нужно предотвратить это, установите default в False в определении класса.
Вы можете предоставить несколько подклассов AppConfig с различным поведением. Чтобы указать Django, какой из них использовать по умолчанию, установите default в True в его определении. Если пользователи захотят выбрать нестандартную конфигурацию, они должны заменить 'rock_n_roll' полным именем этого конкретного класса в настройке INSTALLED_APPS.
Атрибут AppConfig.name сообщает Django, к какому приложению относится эта конфигурация. Вы можете определить любые другие атрибуты, описанные в справке API AppConfig.
AppConfig подклассы могут быть определены в любом месте. Конвенция apps.py просто позволяет Django загружать их автоматически, когда INSTALLED_APPS содержит путь к модулю приложения, а не к классу конфигурации.
Примечание
Если ваш код импортирует реестр приложений в модуль __init__.py приложения, имя apps будет конфликтовать с подмодулем apps. Лучшей практикой является перемещение этого кода в подмодуль и его импорт. Обходным путём является импорт реестра под другим именем:
from django.apps import apps as django_apps
В предыдущих версиях использовалась переменная default_app_config в модуле приложения для идентификации класса конфигурации приложения по умолчанию.
Для пользователей приложения
Если вы используете «Рок-н-ролл» в проекте под названием anthology, но хотите, чтобы он отображался как «Джаз Мануш», вы можете предоставить собственную конфигурацию:
# anthology/apps.py
from rock_n_roll.apps import RockNRollConfig
class JazzManoucheConfig(RockNRollConfig):
verbose_name = "Jazz Manouche"
# anthology/settings.py
INSTALLED_APPS = [
'anthology.apps.JazzManoucheConfig',
# ...
]
Этот пример демонстрирует специфичные для проекта классы конфигурации, расположенные в подмодуле apps.py. Это конвенция, а не требование. AppConfig подклассы могут быть определены в любом месте.
В этой ситуации, INSTALLED_APPS должен содержать полное имя класса конфигурации, потому что он находится вне приложения и, следовательно, не может быть автоматически обнаружен.
Конфигурация приложения
-
class AppConfig -
Объекты конфигурации приложения хранят метаданные для приложения. Некоторые атрибуты можно настроить в подклассах
AppConfig. Другие устанавливаются Django и являются только для чтения.
Настраиваемые атрибуты
-
AppConfig.name -
Полный путь Python к приложению, например,
'django.contrib.admin'.Этот атрибут определяет, к какому приложению относится конфигурация. Он должен быть установлен во всех подклассах
AppConfig.Он должен быть уникальным в рамках проекта Django.
-
AppConfig.label -
Короткое имя приложения, например
'admin'Этот атрибут позволяет переименовать приложение, когда два приложения имеют конфликтующие имена. По умолчанию он равен последнему элементу
name. Он должен быть допустимым идентификатором Python.Он должен быть уникальным в рамках проекта Django.
-
AppConfig.verbose_name -
Имя приложения, понятное человеку, например, «Администрирование».
Этот атрибут по умолчанию
label.title().
-
AppConfig.path -
Путь к файловой системе к каталогу приложения, например,
'/usr/lib/pythonX.Y/dist-packages/django/contrib/admin'.В большинстве случаев Django может автоматически определить и установить его, но вы также можете предоставить явную перезапись в качестве атрибута класса в вашем подклассе
AppConfig. В некоторых ситуациях это требуется; например, если пакет приложения является пакетом пространства имён с несколькими путями.
-
AppConfig.default -
Новое в Django 3.2.
Установите это свойство в значение
False, чтобы предотвратить автоматический выбор Django класса конфигурации. Это полезно, когдаapps.pyопределяет только один подклассAppConfig, но вы не хотите, чтобы Django его использовал по умолчанию.Установите это свойство в значение
True, чтобы указать Django на автоматический выбор класса конфигурации. Это полезно, когдаapps.pyопределяет более одного подклассаAppConfigи вы хотите, чтобы Django использовал один из них по умолчанию.По умолчанию это свойство не задано.
-
AppConfig.default_auto_field -
Новое в Django 3.2.
Неявный тип первичного ключа, который нужно добавить к моделям в этом приложении. Можно использовать его для сохранения
AutoFieldв качестве типа первичного ключа для приложений сторонних разработчиков.По умолчанию это значение
DEFAULT_AUTO_FIELD.
Только для чтения атрибуты
-
AppConfig.module -
Основной модуль приложения, например,
<module 'django.contrib.admin' from 'django/contrib/admin/__init__.py'>.
-
AppConfig.models_module -
Модуль, содержащий модели, например,
<module 'django.contrib.admin.models' from 'django/contrib/admin/models.py'>.Может быть
None, если приложение не содержит модульmodels. Обратите внимание, что связанные с базой данных сигналы, такие какpre_migrateиpost_migrate, генерируются только для приложений, имеющих модульmodels.
Методы
-
AppConfig.get_models() -
Возвращает итерируемый объект классов
Modelдля этого приложения.Требуется, чтобы реестр приложений был полностью заполнен.
-
AppConfig.get_model(model_name, require_ready=True) -
Возвращает
Modelс заданнымmodel_name.model_nameнечувствителен к регистру.Вызывает
LookupError, если такая модель не существует в этом приложении.Требуется, чтобы реестр приложений был полностью заполнен, если аргумент
require_readyне установлен в значениеFalse.require_readyведет себя точно так же, как вapps.get_model().
-
AppConfig.ready() -
Подклассы могут переопределить этот метод для выполнения задач инициализации, таких как регистрация сигналов. Он вызывается сразу после того, как реестр будет полностью заполнен.
Хотя вы не можете импортировать модели на уровне модуля, где определены классы
AppConfig, вы можете импортировать их вready(), используя операторimportилиget_model().Если вы регистрируете
model signals, вы можете сослаться на отправителя по его строковой метке вместо использования самого класса модели.Пример:
from django.apps import AppConfig from django.db.models.signals import pre_save class RockNRollConfig(AppConfig): # ... def ready(self): # importing model classes from .models import MyModel # or... MyModel = self.get_model('MyModel') # registering signals with the model's string label pre_save.connect(receiver, sender='app_label.MyModel')Предупреждение
Хотя вы можете получить доступ к классам моделей, как описано выше, избегайте взаимодействия с базой данных в реализации вашего метода
ready(). Это включает методы моделей, которые выполняют запросы (save(),delete(), методы менеджеров и т. д.), а также запросы к SQL черезdjango.db.connection. Ваш методready()будет выполняться при запуске каждой команды управления. Например, даже несмотря на то, что конфигурация базы данных для тестов отличается от конфигурации для производства,manage.py testпо-прежнему будет выполнять некоторые запросы к вашей **производственной** базе данных!Примечание
В стандартном процессе инициализации метод
readyвызывается Django только один раз. Но в некоторых особых случаях, особенно в тестах, которые изменяют установленные приложения,readyможет вызываться более одного раза. В этом случае либо напишите идемпотентные методы, либо поместите флаг в ваши классыAppConfigдля предотвращения повторного выполнения кода, который должен выполняться ровно один раз.
Пространства имен пакетов как приложения
Пакеты Python без файла __init__.py известны как «пространства имен пакетов» и могут быть распространены по нескольким каталогам в разных местах на sys.path (см. PEP 420).
Приложения Django требуют одного базового пути к файловой системе, где Django (в зависимости от конфигурации) будет искать шаблоны, статические ресурсы и т. д. Таким образом, пакеты пространств имен могут быть приложениями Django только в том случае, если выполняется одно из следующих условий:
- Пакет пространства имен фактически имеет только одно расположение (т. е. не распространён по более чем одному каталогу.)
- Класс
AppConfig, используемый для настройки приложения, имеет атрибут классаpath, который является абсолютным путём к каталогу, который Django будет использовать в качестве единственного базового пути к приложению.
Если ни одно из этих условий не выполняется, Django вызовет ImproperlyConfigured.
Реестр приложений
-
apps -
Реестр приложений предоставляет следующий общедоступный API. Методы, которые не указаны ниже, считаются закрытыми и могут быть изменены без предварительного уведомления.
-
apps.ready -
Булевый атрибут, который устанавливается в значение
Trueпосле того, как реестр будет полностью заполнен, и все методыAppConfig.ready()будут вызваны.
-
apps.get_app_configs() -
Возвращает итерируемый объект экземпляров
AppConfig.
-
apps.get_app_config(app_label) -
Возвращает
AppConfigдля приложения с заданнымapp_label. ВызываетLookupError, если такое приложение не существует.
-
apps.is_installed(app_name) -
Проверяет, существует ли приложение с заданным именем в реестре.
app_name— полное имя приложения, например,'django.contrib.admin'.
-
apps.get_model(app_label, model_name, require_ready=True) -
Возвращает
Modelс заданнымapp_labelиmodel_name. В качестве сокращения, этот метод также принимает один аргумент в видеapp_label.model_name.model_nameнечувствителен к регистру.Вызывает
LookupError, если такое приложение или модель не существует. ВызываетValueError, если вызван с одним аргументом, который не содержит ровно одну точку.Требуется, чтобы реестр приложений был полностью заполнен, если аргумент
require_readyне установлен в значениеFalse.Установка
require_readyв значениеFalseпозволяет искать модели во время заполнения реестра приложений, конкретно во время второй фазы, когда он импортирует модели. Тогдаget_model()имеет тот же эффект, что и импорт модели. Основной пример использования — настройка классов моделей с настройками, такими какAUTH_USER_MODEL.Если
require_readyимеет значениеFalse,get_model()возвращает класс модели, который может быть не полностью функциональным (например, могут отсутствовать обратные аксессоры), пока реестр приложений не будет полностью заполнен. По этой причине лучше всего оставитьrequire_readyпо умолчаниюTrue.
Процесс инициализации
Как загружаются приложения
При запуске Django, функция django.setup() отвечает за заполнение реестра приложений.
-
setup(set_prefix=True)[source] -
Настраивает Django, выполняя:
- Загрузку настроек.
- Настройку ведения журнала.
- Если
set_prefixравно True, устанавливает префикс скрипта обработчика URL наFORCE_SCRIPT_NAME, если он определён, или на/в противном случае. - Инициализацию реестра приложений.
Эта функция вызывается автоматически:
- При запуске HTTP-сервера с помощью WSGI-поддержки Django.
- При вызове команды управления.
В других случаях, например, в простых скриптах Python, её необходимо вызывать явно.
Реестр приложений инициализируется в три этапа. На каждом этапе Django обрабатывает все приложения в порядке INSTALLED_APPS.
-
Вначале Django импортирует каждый элемент из
INSTALLED_APPS.Если это класс конфигурации приложения, Django импортирует корневой пакет приложения, определённый его атрибутом
name. Если это пакет Python, Django ищет конфигурацию приложения в подмодулеapps.py, или же создаёт стандартную конфигурацию приложения.На этом этапе ваш код не должен импортировать модели!
Другими словами, корневые пакеты ваших приложений и модули, которые определяют ваши классы конфигурации приложений, не должны импортировать модели, даже косвенно.
Строго говоря, Django позволяет импортировать модели после загрузки их конфигурации приложения. Однако, чтобы избежать излишних ограничений на порядок
INSTALLED_APPS, настоятельно рекомендуется не импортировать модели на данном этапе.После завершения этого этапа API, которые работают с конфигурациями приложений, такие как
get_app_config(), становятся доступны. -
Затем Django пытается импортировать подмодуль
modelsкаждого приложения, если он существует.Вы должны определить или импортировать все модели в подмодуле
models.pyилиmodels/__init__.pyвашего приложения. В противном случае реестр приложений может не быть полностью заполнен на этом этапе, что может привести к некорректной работе ORM.После завершения этого этапа API, которые работают с моделями, такие как
get_model(), становятся доступны. - Наконец, Django выполняет метод
ready()каждой конфигурации приложения.
Отладка
Вот некоторые распространённые проблемы, которые могут возникнуть во время инициализации:
-
AppRegistryNotReady: Это происходит, когда импорт конфигурации приложения или модуля моделей запускает код, зависящий от реестра приложений.Например,
gettext()использует реестр приложений для поиска каталогов переводов в приложениях. Для перевода во время импорта нужно использоватьgettext_lazy()вместоgettext(). (Использованиеgettext()было бы ошибкой, так как перевод происходил бы во время импорта, а не в каждом запросе, в зависимости от активного языка).Выполнение запросов к базе данных с помощью ORM во время импорта в модулях моделей также вызовет это исключение. ORM не может работать должным образом, пока все модели не будут доступны.
Это исключение также происходит, если вы забыли вызвать
django.setup()в автономном скрипте Python. -
ImportError: cannot import name ...Это происходит, если последовательность импорта приводит к циклу.Чтобы устранить такие проблемы, следует свести к минимуму зависимости между вашими модулями моделей и выполнить как можно меньше работы во время импорта. Для избежания выполнения кода во время импорта, его можно перенести в функцию и кэшировать результаты. Код будет выполнен, когда его результаты понадобятся впервые. Эта концепция известна как «ленивая оценка».
-
django.contrib.adminавтоматически выполняет автоматическое обнаружение модулейadminв установленных приложениях. Чтобы этого избежать, измените свойINSTALLED_APPSна'django.contrib.admin.apps.SimpleAdminConfig'вместо'django.contrib.admin'.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.0/ref/applications/