Spec-Zone.ru › Django 3.0

Приложения

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 и необязательно с помощью других механизмов, таких как URLconf, настройки MIDDLEWARE или наследования шаблонов.

Важно понимать, что приложение Django — это набор кода, который взаимодействует с различными частями фреймворка. Нет такого понятия, как объект Application. Однако в нескольких местах Django должен взаимодействовать с установленными приложениями, в основном для конфигурации и интроспекции. Вот почему реестр приложений хранит метаданные в экземпляре AppConfig для каждого установленного приложения.

Нет ограничения, что пакет проекта не может также считаться приложением и иметь модели и т. д. (что потребовало бы добавления его в INSTALLED_APPS).

Настройка приложений

Для настройки приложения необходимо унаследовать от класса AppConfig и поместить полное имя этого подкласса в INSTALLED_APPS.

Когда INSTALLED_APPS содержит полное имя модуля приложения, Django проверяет наличие переменной default_app_config в этом модуле.

Если она определена, это полное имя подкласса AppConfig для данного приложения.

Если default_app_config не определена, Django использует базовый класс AppConfig.

default_app_config позволяет приложениям, существовавшим до Django 1.7, таким как django.contrib.admin, подключиться к функциям AppConfig без необходимости обновлять их INSTALLED_APPS.

Новые приложения должны избегать default_app_config. Вместо этого они должны потребовать, чтобы полное имя соответствующего подкласса AppConfig было явно настроено в INSTALLED_APPS.

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

Если вы создаёте подключаемое приложение под названием «Rock ’n’ roll», вот как вы можете предоставить правильное имя для админки:

# rock_n_roll/apps.py

from django.apps import AppConfig

class RockNRollConfig(AppConfig):
    name = 'rock_n_roll'
    verbose_name = "Rock ’n’ roll"

Вы можете сделать так, чтобы ваше приложение загружало этот подкласс AppConfig по умолчанию следующим образом:

# rock_n_roll/__init__.py

default_app_config = 'rock_n_roll.apps.RockNRollConfig'

Это заставит использовать RockNRollConfig когда INSTALLED_APPS содержит 'rock_n_roll'. Это позволяет вам использовать возможности AppConfig без необходимости обновления пользователей их INSTALLED_APPS настройки. Помимо этого случая, лучше избегать использования default_app_config и вместо этого указать класс конфигурации приложения в INSTALLED_APPS, как описано ниже.

Конечно, вы также можете сказать своим пользователям, чтобы они поместили 'rock_n_roll.apps.RockNRollConfig' в свою настройку INSTALLED_APPS. Вы даже можете предоставить несколько различных подклассов AppConfig с различным поведением и позволить вашим пользователям выбрать один через настройку INSTALLED_APPS.

Рекомендуемая конвенция — поместить класс конфигурации в подмодуль приложения под названием apps. Однако Django этого не требует.

Вы должны включить атрибут name, чтобы Django определил, к какому приложению относится эта конфигурация. Вы можете определить любые атрибуты, описанные в справке по API AppConfig.

Примечание

Если ваш код импортирует реестр приложений в модуль __init__.py приложения, имя apps будет конфликтовать с подмодулем apps. Лучшей практикой является перемещение этого кода в подмодуль и его импорт. Обходным путём является импорт реестра под другим именем:

from django.apps import apps as django_apps

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

Если вы используете «Rock ’n’ roll» в проекте под названием anthology, но хотите, чтобы оно отображалось как «Jazz Manouche», вы можете предоставить собственную конфигурацию:

# 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 является конвенцией, а не требованием.

Конфигурация приложений

class AppConfig [source]

Объекты конфигурации приложения хранят метаданные для приложения. Некоторые атрибуты могут быть настроены в подклассах AppConfig. Другие устанавливаются Django и являются только для чтения.

Настраиваемые атрибуты

AppConfig.name

Полное имя пути к приложению, например '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.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() [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'.

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 создаёт конфигурацию приложения по умолчанию.

    На данном этапе ваш код не должен импортировать модели!

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

    Строго говоря, 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.0/ref/applications/

Spec-Zone.ru

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