Spec-Zone.ru › Django 4.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», вот как вы можете предоставить правильное имя для администратора:

# 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

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

Если вы используете «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.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

Установите этот атрибут в 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)

Возвращает итерируемый список классов 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-сервера с помощью Django ASGI или WSGI.
  • При вызове команды управления.

В других случаях её необходимо вызывать явно, например, в обычных 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(). (Использование 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.2/ref/applications/

Spec-Zone.ru

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