⒈、django项目启动时,自定义执行某个py文件。
在任意的app的apps.py中的Config类中定义ready方法,并调用autodiscover_modules
1 from django.apps import AppConfig 2 from django.utils.module_loading import autodiscover_modules 3 4 class StarkConfig(AppConfig): 5 name = 'stark' 6 7 def ready(self): 8 autodiscover_modules('stark')
django在启动时,就会去已注册的所有app的目录下找 apps.py 并自动导入。
如果执行两次,是因为django内部自动重启导致:
python manage.py runserver 120.0.0.1:8001 --noreload
⒉、单例模式
通过利用Python模块导入的特性:在Python中,如果已经导入过的文件再次被重新导入时候,python不会再重新解释一遍,而是选择从内存中直接将原来导入的值拿来用。
1 def include(arg, namespace=None): 2 app_name = None 3 if isinstance(arg, tuple): 4 # Callable returning a namespace hint. 5 try: 6 urlconf_module, app_name = arg 7 except ValueError: 8 if namespace: 9 raise ImproperlyConfigured( 10 'Cannot override the namespace for a dynamic module that ' 11 'provides a namespace.' 12 ) 13 raise ImproperlyConfigured( 14 'Passing a %d-tuple to include() is not supported. Pass a ' 15 '2-tuple containing the list of patterns and app_name, and ' 16 'provide the namespace argument to include() instead.' % len(arg) 17 ) 18 else: 19 # No namespace hint - use manually provided namespace. 20 urlconf_module = arg 21 22 if isinstance(urlconf_module, str): 23 urlconf_module = import_module(urlconf_module) 24 patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module) 25 app_name = getattr(urlconf_module, 'app_name', app_name) 26 if namespace and not app_name: 27 raise ImproperlyConfigured( 28 'Specifying a namespace in include() without providing an app_name ' 29 'is not supported. Set the app_name attribute in the included ' 30 'module, or pass a 2-tuple containing the list of patterns and ' 31 'app_name instead.', 32 ) 33 namespace = namespace or app_name 34 # Make sure the patterns can be iterated through (without this, some 35 # testcases will break). 36 if isinstance(patterns, (list, tuple)): 37 for url_pattern in patterns: 38 pattern = getattr(url_pattern, 'pattern', None) 39 if isinstance(pattern, LocalePrefixPattern): 40 raise ImproperlyConfigured( 41 'Using i18n_patterns in an included URLconf is not allowed.' 42 ) 43 return (urlconf_module, app_name, namespace)
返回值是由含有三个元素的元祖 (urlconf_module, app_name, namespace)
⒊、django路由分发的本质:include
from django.conf.urls import url,include
from app01 import urls
以往写的include函数实现路由分发
urlpatterns = [
url(r'^rbac/',include(('rbac.urls','rbac'),namespace='rbac'))
]
其实,include函数主要返回有三个元素的元组。 urlpatterns = [ url(r'^web/', (urls, app_name, namespace)), # 第一个参数是urls文件对象,通过此对象可以获取urls.patterns获取分发的路由。 ]
在源码内部,读取路由时:
如有第一个参数有:urls.patterns 属性,那么子路由就从该属性中后去。
如果第一个参数无:urls.patterns 属性,那么子路由就是第一个参数。
综合以上,自己实现的路由分发方式:
1 urlpatterns = [ 2 url(r'^web/', ([ 3 url(r'^index/', views.index), 4 url(r'^home/', views.home), 5 ], app_name, namespace)), # 第一个参数是urls文件对象,通过此对象可以获取urls.patterns获取分发的路由。 6 ]