Spec-Zone.ru › Django 2.0

Приложения

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

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

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

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

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

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

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

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

Добавлена в Django 1.11:

Был добавлен ключевой аргумент require_ready.

AppConfig.ready() [source]

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

Хотя вы не можете импортировать модели на уровне модуля, где определены классы AppConfig, вы можете импортировать их в ready(), используя оператор import или get_model().

Если вы регистрируете model signals, вы можете ссылаться на отправителя по его строковому метке вместо использования самого класса модели.

Пример:

from django.db.models.signals import pre_save

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 whenever possible.

Добавлена в Django 1.11:

Был добавлен ключевой аргумент require_ready.

Процесс инициализации

Как загружаются приложения

При запуске 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/2.0/ref/applications/

Spec-Zone.ru

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