• 3.1
  • 5.0
  • 6.1
  • Версия документации: 3.2

Приложения

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

This registry is called apps and it’s available in 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) обычно является контейнером для всех приложений проекта, которые не устанавливаются отдельно.

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

Приложения содержат набор моделей, представлений, шаблонов, шаблонных тегов, статических файлов, URL-ов, мидлваров, и прочее. Они добавляются в проект через настройку INSTALLED_APPS, подключение в URLconfs, настройку MIDDLEWARE_CLASSES, или наследование шаблонов.

Важно помнить, что приложение 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. Можно вынести этот код в под-модуль приложения и импортировать его в __init__.py. Другой вариант - импортировать реестр под другим названием:

from django.apps import apps as django_apps
Changed in Django 3.2:

In previous versions, a default_app_config variable in the application module was used to identify the default application configuration class.

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

Если вы используете приложение с «Rock ’n’ roll» в проекте, который называется anthology, и хотите заменить на «Gypsy jazz», вы можете добавить свой класс настроек:

# 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.

Должен быть уникальным для проекта.

AppConfig.label

Короткое название(метка) приложения, например 'admin'

Этот атрибут позволяет поменять метку приложения, если два приложения используют по умолчанию одинаковые метки. По умолчанию метка равна последней части значения name. Метка должна быть правильным идентификатором Python.

Должен быть уникальным для проекта.

AppConfig.verbose_name

Читабельное название приложения, например «Administration».

По умолчанию равен label.title().

AppConfig.path

Путь в файловой системе к каталогу с приложением, например '/usr/lib/python3.4/dist-packages/django/contrib/admin'.

В большинстве случае Django может автоматически определить и установить это значение, но вы можете переопределить его в классе наследнике AppConfig. Это может понадобиться в некоторых случаях, например, если пакет приложения является namespace-пакетом и расположен в нескольких каталогах.

AppConfig.default
New in Django 3.2.

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

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

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

AppConfig.default_auto_field
New in Django 3.2.

Тип неявного первичного ключа, добавляемый в модели в этом приложении. Вы можете использовать это, чтобы сохранить AutoField в качестве типа первичного ключа для сторонних приложений.

По умолчанию это значение DEFAULT_AUTO_FIELD.

Неизменяемые атрибуты

AppConfig.module

Корневой модуль приложения, например <module 'django.contrib.admin' from 'django/contrib/admin/__init__.pyc'>.

AppConfig.models_module

Модуль, который содержит модели, например <module 'django.contrib.admin.models' from 'django/contrib/admin/models.pyc'>.

Может быть None, если приложение не содержит модуль models. Обратите внимание, сигналы, связанные с базой данных, такие как pre_migrate и post_migrate, вызываются только для приложений, которые содержат модуль models.

Методы

AppConfig.get_models()

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

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

AppConfig.get_model(model_name, require_ready=True)

Возвращает Model для переданного model_name. Вызывает LookupError, если модель не существует. model_name регистро-независимое значение.

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

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

AppConfig.ready()

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

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

Если вы регистрируете сигналы модели <django.db.models.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() будет вызываться при каждом запуске команды Django. Например, хотя настройка тестовой базы данных отделена от рабочих настроек проекта, manage.py test выполнила бы запросы на рабочей базе данных!

Примечание

In the usual initialization process, the ready method is only called once by Django. But in some corner cases, particularly in tests which are fiddling with installed applications, ready might be called more than once. In that case, either write idempotent methods, or put a flag on your AppConfig classes to prevent re-running code which should be executed exactly one time.

Namespace-пакеты приложений (Python 3.3+)

Python версии 3.3 и выше поддерживает Python пакеты без файла __init__.py. Эти пакеты называют «namespace-пакетами» и могут находится в нескольких каталогах в sys.path (смотрите PEP 420).

Django приложениям необходим один основной путь в файловой системе, где Django (в зависимости от настроек) будет искать шаблоны, статические файлы, и прочее. Таким образом, namespace-пакеты могут быть приложениями Django только при следующих условиях:

  1. Namespace-пакет содержит один каталог (то есть не разделен на несколько каталогов)

  2. Используется класс AppConfig, указывающий в path один абсолютный путь к каталогу, который Django будет использовать как каталог приложения.

Если ни одно из этих условий не соблюдено, Django вызовет исключение ImproperlyConfigured.

Реестр приложений

apps

Реестр приложений предоставляет следующий публичный API. Методы, которые не описаны здесь, являются приватными и могут изменяться в будущем без предупреждений.

apps.ready

Булев атрибут, который устанавливается в True, когда реестр полностью проинициализирован.

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.setup() отвечает за заполнение реестра приложений при запуске Django.

setup(set_prefix=True)

Настраивает Django, выполняя следующие действия:

  • Загрузка настроек.

  • Настройка логирования.

  • Если set_prefix имеет значение True, установка префикса сценария преобразователя URL-адресов в FORCE_SCRIPT_NAME, если он определен, или / в противном случае.

  • Инициализация реестра приложений.

Эта функция вызывается автоматически:

  • When running an HTTP server via Django’s WSGI support.

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

    Например, ugettext() использует реестр приложений для поиска каталогов с файлами локализации. Для локализации на этапе импорта используйте ugettext_lazy(). (Использование ugettext() приведет к багу, т.к. перевод будет выполнен на момент импорта, а не для каждого запрос с учетом активной локалид.)

    Выполнение запросов к базе данных с помощью ORM в процессе импорта модуля моделей вызовет исключение. ORM не может работать, пока все модели не будут загружены.

    Эта ошибка также вызывается, если django.setup() не был вызван в Python скрипте.

  • ImportError: cannot import name .... Ошибка вызывается при циклических импортах.

    Для устранения таких проблем необходимо минимизировать зависимости между модулями моделей и в процессе импорта выполнять минимум действий. Чтобы избежать выполнения кода на этапе импорта, вынесите его в функцию, которая умеет кэшировать результат. Затем вызовите функции при необходимости. Такая концепция называется «ленивое выполнение».

  • django.contrib.admin автоматически выполняет регистрацию модулей admin установленных приложений. Чтобы отключить это, укажите в INSTALLED_APPS 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin'.

Back to Top