Spec-Zone.ru › Django 2.1

Приложения

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/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

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

Если вы используете «Рок-н-ролл» в проекте под названием 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 является соглашением, а не требованием.

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

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.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.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 всякий раз, когда это возможно.

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

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

Когда 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.1/ref/applications/

Spec-Zone.ru

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