#URLの設定でinclude は実際何してるんだろう?
include()を使用してPATHの設定を引きとれるとなっているが、実際何をしているんだろう
(参考)
mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
実際の関数内原文
def include(arg, namespace=None):
app_name = None
if isinstance(arg, tuple):
try:
urlconf_module, app_name = arg
except ValueError:
if namespace:
raise ImproperlyConfigured(
'Cannot override the namespace for a dynamic module that '
'provides a namespace.'
)
raise ImproperlyConfigured(
'Passing a %d-tuple to include() is not supported. Pass a '
'2-tuple containing the list of patterns and app_name, and '
'provide the namespace argument to include() instead.' % len(arg)
)
else:
urlconf_module = arg
if isinstance(urlconf_module, str):
urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
app_name = getattr(urlconf_module, 'app_name', app_name)
if namespace and not app_name:
raise ImproperlyConfigured(
'Specifying a namespace in include() without providing an app_name '
'is not supported. Set the app_name attribute in the included '
'module, or pass a 2-tuple containing the list of patterns and '
'app_name instead.',
)
namespace = namespace or app_name
if isinstance(patterns, (list, tuple)):
for url_pattern in patterns:
pattern = getattr(url_pattern, 'pattern', None)
if isinstance(pattern, LocalePrefixPattern):
raise ImproperlyConfigured(
'Using i18n_patterns in an included URLconf is not allowed.'
)
return (urlconf_module, app_name, namespace)
ここから調べた結果
def include(arg, namespace=None):
arg は必須 namespace は任意
if isinstance(arg, tuple):
arg が tuple型(配列)かチェックしている (isinstance関数)
urlconf_module, app_name = arg
arg = ('a','b') の場合
urlconf_module ='a'
app_name = 'b' となる
arg = ('a','b','c') の場合はエラーになる
エラーの場合は例外で返る
このことにより
arg = 'hoge'
or
arg = ('hoge','fuga')
が通過できるようになるということがわかる
if isinstance(urlconf_module, str):
urlconf_module = import_module(urlconf_module)
urlconf_module が文字列かどうかチェックしている
文字列の場合 import_module の関数を実行している
呼び出されている import_module について
/AppData/Local/Programs/Python/Python38/Lib/importlib/__init__.py
def import_module(name, package=None):
level = 0
if name.startswith('.'):
if not package:
msg = ("the 'package' argument is required to perform a relative "
"import for {!r}")
raise TypeError(msg.format(name))
for character in name:
if character != '.':
break
level += 1
return _bootstrap._gcd_import(name[level:], package, level)
import moduleに関する調査
if name.startswith('.'):
文字列の最初が'.'で始まっているか調べる startswith
if not package:
ここはtrueが返ってくる?
ならエラーで終わるやん。
for character in name:
if character != '.':
break
level += 1
ここでは、最初の'.'以外の文字が出るまで繰り返す。
「../test」なら「/test」になる様子
しかし、ここではlavel=0以外はかんがえられない
return _bootstrap._gcd_import(name[level:], package, level)
name[level:] nameの文字列
package は None
level は 0
※name[level:] は
name[0:] と同じで文字列の切り出しです。
name[最初の文字位置:最後の文字位置] という意味
数字が入っていないと必然的に一番最初・一番最後という意味になる。
呼び出されている _bootstrap._gcd_import について
C:\Users\(ユーザー名)\AppData\Local\Programs\Python\Python38\Lib\importlib\_bootstrap.py
def _gcd_import(name, package=None, level=0):
_sanity_check(name, package, level)
if level > 0:
name = _resolve_name(name, package, level)
return _find_and_load(name, _gcd_import)
level は0しかありえないので必然的に return _find_and_load (name, _gcd_import)
name はそのまま引き継がれ、
_gcd_import は実行された関数が含まれている
関数を引数に入れる発想がなかった!
呼び出されている _find_and_loadについて
C:\Users\(ユーザー名)\AppData\Local\Programs\Python\Python38\Lib\importlib\_bootstrap.py
def _find_and_load(name, import_):
"""Find and load the module."""
with _ModuleLockManager(name):
module = sys.modules.get(name, _NEEDS_LOADING)
if module is _NEEDS_LOADING:
return _find_and_load_unlocked(name, import_)
if module is None:
message = ('import of {} halted; '
'None in sys.modules'.format(name))
raise ModuleNotFoundError(message, name=name)
_lock_unlock_module(name)
return module