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

Приложения

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

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

To configure an application, subclass AppConfig and put the dotted path to that subclass in INSTALLED_APPS.

When INSTALLED_APPS contains the dotted path to an application module, Django checks for a default_app_config variable in that module.

If it’s defined, it’s the dotted path to the AppConfig subclass for that application.

If there is no default_app_config, Django uses the base AppConfig class.

default_app_config allows applications that predate Django 1.7 such as django.contrib.admin to opt-in to AppConfig features without requiring users to update their INSTALLED_APPS.

New applications should avoid default_app_config. Instead they should require the dotted path to the appropriate AppConfig subclass to be configured explicitly in 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"

You can make your application load this AppConfig subclass by default as follows:

# rock_n_roll/__init__.py

default_app_config = 'rock_n_roll.apps.RockNRollConfig'

That will cause RockNRollConfig to be used when INSTALLED_APPS contains 'rock_n_roll'. This allows you to make use of AppConfig features without requiring your users to update their INSTALLED_APPS setting. Besides this use case, it’s best to avoid using default_app_config and instead specify the app config class in INSTALLED_APPS as described next.

You can also tell your users to put 'rock_n_roll.apps.RockNRollConfig' in their INSTALLED_APPS setting. You can even provide several different AppConfig subclasses with different behaviors and allow your users to choose one via their INSTALLED_APPS setting.

The recommended convention is to put the configuration class in a submodule of the application called apps. However, this isn’t enforced by Django.

You must include the name attribute for Django to determine which application this configuration applies to. You can define any attributes documented in the AppConfig API reference.

Примечание

Если ваш код импортирует реестр приложений в __init__.py приложения, название apps будет пересекаться с под-модулем apps. Можно вынести этот код в под-модуль приложения и импортировать его в __init__.py. Другой вариант - импортировать реестр под другим названием:

from django.apps import apps as django_apps

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

Если вы используете приложение с «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',
    # ...
]

Again, defining project-specific configuration classes in a submodule called apps is a convention, not a requirement.

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

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

    If it’s an application configuration class, Django imports the root package of the application, defined by its name attribute. If it’s a Python package, Django creates a default application configuration.

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

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

    По правде говоря, 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