Spec-Zone.ru › Django 3.2

Приложения

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
Изменено в Django 3.2:

В предыдущих версиях использовалась переменная 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 только в том случае, если выполняется одно из следующих условий:

  1. Пространство имён пакета фактически имеет только одно расположение (т. е. не распределено по нескольким каталогам).
  2. Класс 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.

  1. Сначала Django импортирует каждый элемент из INSTALLED_APPS.

    Если это конфигурационный класс приложения, Django импортирует корневой пакет приложения, определённый его атрибутом name. Если это пакет Python, Django ищет конфигурацию приложения в подмодуле apps.py, или же создаёт конфигурацию по умолчанию.

    На этом этапе не следует импортировать модели!

    Другими словами, корневые пакеты ваших приложений и модули, определяющие классы конфигурации приложений, не должны импортировать модели, даже косвенно.

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

    После завершения этого этапа становятся доступными API, работающие с конфигурациями приложений, такие как get_app_config().

  2. Затем Django пытается импортировать подмодуль models каждого приложения, если он существует.

    Все модели в подмодуле models.py или models/__init__.py приложения должны быть определены или импортированы. В противном случае реестр приложений может быть не полностью заполнен, что может привести к некорректной работе ORM.

    После завершения этого этапа становятся доступными API, работающие с моделями, такие как get_model().

  3. Наконец, Django выполняет метод ready() каждой конфигурации приложения.

Отладка проблем

Ниже приведены некоторые распространённые проблемы, которые могут возникнуть во время инициализации:

  • AppRegistryNotReady: Это происходит, когда импорт конфигурации приложения или модуля моделей вызывает код, зависящий от реестра приложений.

    Например, gettext() использует реестр приложений для поиска каталогов перевода в приложениях. Для перевода во время импорта необходимо использовать gettext_lazy() вместо этого. (Использование 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/3.2/ref/applications/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API