Spec-Zone.ru › Django 1.10

Приложения

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-адресов, среднего программного обеспечения и т. д. Они обычно подключаются к проектам с помощью настройки 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/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'

Это заставит Django использовать 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/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) [source]

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

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

Возвращает Model с заданными app_label и model_name. В качестве сокращения этот метод также принимает один аргумент в формате app_label.model_name. model_name нечувствительно к регистру.

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

Процесс загрузки приложений

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

При запуске 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.contrib.auth.get_user_model(). Используйте настройку AUTH_USER_MODEL для ссылки на модель пользователя во время импорта.

    Эта ошибка также возникает, если вы забыли вызвать 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.10/ref/applications/

Spec-Zone.ru

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