Spec-Zone.ru › Django 4.1

Приложения

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

Этот реестр называется apps, и он доступен в django.apps:

>>> from django.apps import apps
>>> apps.get_app_config('admin').verbose_name
'Administration'

Проекты и приложения

Термин проект описывает веб-приложение Django. Пакет Python проекта определяется в первую очередь модулем настроек, но обычно содержит и другие вещи. Например, при запуске django-admin startproject mysite вы получите mysite директорию проекта, которая содержит mysite пакет Python с settings.py, urls.py, asgi.py и wsgi.py. Пакет проекта часто расширяется, чтобы включать такие вещи, как фикстуры, CSS и шаблоны, которые не привязаны к конкретному приложению.

Корневая директория проекта (та, которая содержит manage.py) обычно является контейнером для всех приложений проекта, которые не установлены отдельно.

Термин приложение описывает пакет Python, который предоставляет набор функций. Приложения могут быть повторно использованы в различных проектах.

Приложения включают в себя некоторую комбинацию моделей, представлений, шаблонов, тегов шаблонов, статических файлов, URL-адресов, мидлвеаров и т. д. Обычно они подключаются к проектам с помощью настройки INSTALLED_APPS и необязательно с помощью других механизмов, таких как URLconf, настройки 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

Для пользователей приложений

Если вы используете «Рок-н-ролл» в проекте под названием 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 [source]

Объекты конфигурации приложения хранят метаданные для приложения. Некоторые атрибуты можно настроить в подклассах 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

Установите это свойство в False, чтобы предотвратить автоматический выбор Django класса конфигурации. Это полезно, когда apps.py определяет только один подкласс AppConfig, но вы не хотите, чтобы Django использовал его по умолчанию.

Установите это свойство в True, чтобы указать Django выбрать класс конфигурации автоматически. Это полезно, когда apps.py определяет более одного подкласса AppConfig и вы хотите, чтобы Django использовал один из них по умолчанию.

По умолчанию это свойство не установлено.

AppConfig.default_auto_field

Неявный тип первичного ключа для добавления в модели в этом приложении. Вы можете использовать это, чтобы сохранить 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(include_auto_created=False, include_swapped=False) [source]

Возвращает итерируемый объект с классами Model для этого приложения.

Требует, чтобы реестр приложений был полностью заполнен.

AppConfig.get_model(model_name, require_ready=True) [source]

Возвращает Model с заданным model_name. model_name нечувствителен к регистру.

Возбуждает LookupError, если такая модель не существует в этом приложении.

Требует, чтобы реестр приложений был полностью заполнен, если аргумент require_ready не установлен в False. require_ready ведет себя точно так же, как в apps.get_model().

AppConfig.ready() [source]

Подклассы могут переопределять этот метод для выполнения задач инициализации, таких как регистрация сигналов. Он вызывается сразу после того, как реестр будет полностью заполнен.

Хотя вы не можете импортировать модели на уровне модуля, где определены классы 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'.

END_OF_DOCUMENT_MARKER
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/4.1/ref/applications/

Spec-Zone.ru

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