Приложения

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

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

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

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

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

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

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

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

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

класс AppConfig[источник]

Объекты конфигурации приложения хранят метаданные для приложения. Некоторые атрибуты можно настроить в подклассах AppConfig . Остальные определены Django и доступны только для чтения.

Настраиваемые атрибуты

AppConfig.name

Полный путь Python к приложению, например 'django.contrib.admin' ,

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

Он должен быть уникальным в контексте того же проекта Django.

AppConfig.label

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

Этот атрибут используется для изменения метки приложения, когда два приложения имеют несовместимые метки. По умолчанию label это последний элемент 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() [источник]

Возвращает повторяемый объект классов Model для этого приложения.

Требуется полное определение реестра приложений.

AppConfig.get_model( Model_name , require_ready = True ) [источник]

Возвращает класс Model с model_name заданным именем . model_name нечувствителен к регистру.

Генерируется, LookupError если в этом приложении не существует шаблона с таким именем.

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

AppConfig.ready() [источник]

Подклассы могут расширять этот метод для выполнения задач инициализации, таких как регистрация сигналов. Он вызывается, как только реестр будет полностью заполнен.

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

Если вы зарегистрируетесь , вы можете ссылаться на отправителя по его текстовой метке вместо использования самого класса шаблона.signaux de modèle

Пример:

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() выполняется при запуске каждой команды управления. Например, несмотря на то, что конфигурация тестовой базы данных отделена от производственных параметров, все же можно выполнять запросы к вашей производственной базе данных  !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 - полное название приложения, например. '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 ) [источник]

Настраивает 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' .

Copyright ©2020 All rights reserved