импорт ОС
из importlib импорта import_module
от django.core.exceptions импорта ImproperlyConfigured
из django.utils.module_loading импорта module_has_submodule
MODELS_MODULE_NAME = 'модели'
[docs] class AppConfig :
"" "Класс, представляющий приложение Django и его конфигурацию." ""
def __init__ ( self , app_name , app_module ):
# Полный путь Python к приложению, например, 'django.contrib.admin'.
я . name = app_name
# Корневой модуль для приложения, например <module 'django.contrib.admin'
# из 'django / contrib / admin / __ init __. Py'>.
я . модуль = app_module
# Ссылка на реестр приложений, содержащий этот AppConfig. Устанавливается
реестром # при регистрации экземпляра AppConfig.
я . apps = Нет
# Следующие атрибуты могут быть определены на уровне класса в
подклассе #, отсюда и шаблон test-and-set.
# Последний компонент пути Python к приложению, например, admin.
# Это значение должно быть уникальным для проекта Django.
если не hasattr ( self , 'label' ):
self . label = app_name . распределение ( "." ) [ 2 ]
# Удобочитаемое имя приложения, например "Admin".
если не hasattr ( self , 'verbose_name' ):
self . verbose_name = self . этикетка . название ()
# Путь файловой системы к каталогу приложения, например
# '/ path / to / django / contrib / admin'.
если не hasattr ( self , 'path' ):
self . путь = себя . _path_from_module ( модуль_приложения )
# Модуль, содержащий модели, например, <module 'django.contrib.admin.models'
# из 'django / contrib / admin / models.py'>. Устанавливается import_models ().
# Нет, если в приложении нет модуля моделей.
я . models_module = Нет
# Сопоставление имен моделей в нижнем регистре с классами моделей. Изначально установлено значение
# None для предотвращения случайного доступа перед запуском import_models ().
я . models = Нет
def __repr__ ( self ):
return '< % s : % s >' % ( self . __class__ . __name__ , self . label )
def _path_from_module ( self , module ):
"" "Попытка определить путь к файловой системе приложения из его модуля." ""
# См. # 21874 для расширенного обсуждения поведения этого метода в
# различных случаях.
# Преобразование путей в список, потому что _NamespacePath Python не поддерживает
# индексацию.
paths = list ( getattr ( module , '__path__' , []))
if len ( paths ) ! = 1 :
filename = getattr ( module , '__file__', Ни один ) ,
если имя файла не является не None :
пути = [ ос . путь . dirname ( filename )]
else :
# По неизвестным причинам иногда список, возвращаемый __path__
#, содержит дубликаты, которые необходимо удалить (# 25246).
paths = list ( set ( paths ))
if len ( paths ) > 1 :
raise ImproperlyConfigured (
"Модуль приложения % rимеет несколько расположений файловой системы ( % r ); "
" вы должны настроить это приложение с помощью подкласса AppConfig "
" с атрибутом класса 'path. " % ( module , paths ))
elif not paths :
raise ImproperlyConfigured (
" Модуль приложения % r не имеет расположения в файловой системе "
", вы необходимо настроить это приложение с подклассом AppConfig "
" с атрибутом класса 'path'. " % module )"
пути возврата [ 0 ]
@classmethod
def create ( cls , entry ):
"" "
Фабрика, которая создает конфигурацию приложения из записи в INSTALLED_APPS.
" ""
try :
# Если import_module успешно, запись - это путь к модулю приложения,
# который может указывать приложение config класс с default_app_config.
# В противном случае запись - это путь к классу конфигурации приложения или ошибка.
модуль = import_module ( запись )
except ImportError :
# Отследить, что импорт как модуль приложения не удался. Если импорт как
конфигурационный класс приложения # тоже не удастся, мы снова вызовем ImportError.
модуль = Нет
mod_path , _ , cls_name = запись . распределение ( '.' )
# Вызывает исходное исключение, если запись не может быть путем
# к классу конфигурации приложения.
если не mod_path :
поднять
else :
try :
# Если это работает, модуль приложения указывает класс конфигурации приложения.
запись = модуль . default_app_config
except AttributeError :
# В противном случае он просто использует класс конфигурации приложения по умолчанию.
return cls ( entry , module )
else :
mod_path , _ , cls_name = entry . распределение ( '.' )
# Если мы достигаем этой точки, мы должны попытаться загрузить
класс
конфигурации приложения #, расположенный по адресу <mod_path>. <cls_name> mod = import_module ( mod_path )
try :
cls = getattr ( mod , cls_name )
except AttributeError :
if module is Нет :
# Если импорт как модуль приложения завершился неудачно, проверьте,
# содержит ли
модуль какие-либо допустимые конфигурации AppConfigs, и покажите их как варианты выбора. # В противном случае эта ошибка, вероятно, содержит самую информативную
# трассировку, поэтому вызовите ее снова.
кандидаты = отсортировано(
repr ( имя ) для имени , кандидата в мод . __dict__ . items (),
если isinstance ( кандидат , тип ) и
issubclass ( кандидат , AppConfig ), а
кандидат не является AppConfig ), если кандидаты : поднять ImproperlyConfigured ( "' % s ' не содержат класс " % s ". Возможные варианты: % s
. "
% ( mod_path , cls_name , ',' . join ( кандидаты ))
)
import_module ( запись )
еще :
поднять
# Проверить на очевидные ошибки. (Эта проверка предотвращает утиной типизации, но
# это может быть удален , если это стало проблемой на практике.)
Если не issubclass ( ЦБС , AppConfig ):
повышение ImproperlyConfigured (
«„ % s “не является подклассом AppConfig.» % Вход )
# Получите имя приложения здесь, а не в AppClass .__ init__, чтобы
# все проверки ошибок для записей в INSTALLED_APPS были в одном месте.
попробуйте :
app_name = cls . name
за исключением AttributeError :
поднять ImproperlyConfigured (
«' % s ' должен содержать атрибут имени.» % entry )
# Убедитесь, что app_name указывает на допустимый модуль.
попробуйте :
app_module = import_module ( app_name ) , за
исключением ImportError :
повышение ImproperlyConfigured (
"Невозможно импортировать ' % s '. Проверьте , что ' % s . % s . .name' правильно" % (
app_name , mod_path , cls_name ,
)
)
# Entry - это путь к классу конфигурации приложения.
return cls ( app_name , app_module )
[docs] def get_model ( self , model_name , require_ready = True ):
"" "
Возвращает модель с заданным именем model_name без учета регистра.
Поднимите LookupError, если модели с таким именем не существует.
"" "
if require_ready :
self . apps . check_models_ready ()
else :
self . apps . check_apps_ready ()
try :
return self . models [ model_name . lower ()]
except KeyError :
raise LookupError (
" Приложение ' % s ' не есть модель ' % s '. " % ( self .label , model_name ))
[docs] def get_models ( self , include_auto_created = False , include_swapped = False ):
"" "
Возвращает итерацию моделей.
По умолчанию следующие модели не включены:
- автоматически созданные модели для отношений «многие ко многим» без
явной промежуточной таблицы,
- модели, которые были заменены местами.
Задайте для соответствующего аргумента ключевого слова значение True, чтобы включить такие модели.
Аргументы ключевых слов не задокументированы; это частный API.
"" "
self . apps . check_models_ready ()
для модели в self . models . values ():
if model . _meta . auto_created and not include_auto_created :
продолжить,
если model . _meta . заменен, а не include_swapped :
продолжить
модель доходности
def import_models ( self ):
# Словарь моделей для этого приложения, который в основном поддерживается в
атрибуте # all_models приложений, к которым прикреплен этот AppConfig.
я . модели = себя . приложения . all_models [ сам . label ]
если module_has_submodule ( self . module , MODELS_MODULE_NAME ):
models_module_name = ' % s . % S ' % ( сам . Имя , MODELS_MODULE_NAME )
самостоятельно . models_module = import_module ( models_module_name )
[docs] def ready ( self ):
"" "
Переопределить этот метод в подклассах для запуска кода при запуске Django.
" ""