Spec-Zone.ru › Django 1.11

Приложения

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

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

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

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

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

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

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

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

Полный путь к приложению в Python, например '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__.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() [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 вызывается Джанго только один раз. Но в некоторых крайних случаях, особенно в тестах, которые играют с установленными приложениями, __init__.py может быть вызван более одного раза. В этом случае либо напишите идемпотентные методы, либо поместите флаг на ваши классы AppConfig, чтобы предотвратить повторное выполнение кода, который должен выполняться ровно один раз.

Пакеты имен как приложения (Python 3.3+)

Версии Python 3.3 и выше поддерживают пакеты 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 1.11:

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

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

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

При запуске Django за заполнение реестра приложений отвечает django.setup().

setup(set_prefix=True) [source]

Настраивает Django следующим образом:

  • Загрузка настроек.
  • Настройка ведения журналов.
  • Если set_prefix True, установка префикса скрипта распознавания URL на FORCE_SCRIPT_NAME, если определён, или / в противном случае.
  • Инициализация реестра приложений.
Изменено в Django 1.10:

Новая возможность установки префикса скрипта распознавания URL.

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

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

    Например, 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'.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.11/ref/applications/

Spec-Zone.ru

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