赞
踩
importlib模块为用户提供了动态导入自定义对象的途径。比如自定义三个权限验证模块
" Press ? for help | 1 class Authentication: | 2 def __init__(self): .. (up a dir) | 3 ¦ print ('Has First Authentication') </Desktop/learn/django/auth/ |~ __init__.py |~ firauthentication.py |~ secauthentication.py |~ thiauthentication.py | firauthentication.py pyt… 33% ☰ 1/3 ㏑ : 1 ~ | 1 class Authentication: ~ | 2 def __init__(self): ~ | 3 ¦ print ('Has Second Authentication') ~ |~ ~ |~ ~ |~ ~ |~ ~ | secauthentication.py pyt… 33% ☰ 1/3 ㏑ : 9 ~ | 1 class Authentication: ~ | 2 def __init__(self): ~ | 3 ¦ print ('Has Second Authentication') ~ |~ ~ |~ ~ |~ ~ |~ <arx/Desktop/learn/django/auth thiauthentication.py pyt… 33% ☰ 1/3 ㏑ : 1
现在可以根据配置文件导入应用中:
>>> import importlib
>>> AUTHENTICATION_LIST = ['auth.firauthentication', 'auth.secauthentication']
>>> for AUTH in AUTHENTICATION_LIST:
... authModule = importlib.import_module(AUTH) # 获取模块
... print(authModule) # 检查模块对象
... print(type(authModule)) # 检查获取的对象的类型
... auth = getattr(authModule, 'Authentication') # 获取定在模块内的'Authentication'类对象
... realAuth = auth() # 实例化类对象
...
<module 'auth.firauthentication' from '/home/starx/Desktop/learn/django/auth/firauthentication.py'>
<class 'module'>
Has First Authentication
<module 'auth.secauthentication' from '/home/starx/Desktop/learn/django/auth/secauthentication.py'>
<class 'module'>
Has Second Authentication
可以看到import_module方法接受以点分隔的模块路径,并返回该模块,此时可以调用模块中的内容。
Django中多次使用importlib模块,以权限验证为例,django.auth模块中定义了_get_backends方法,此方法会返回所有配置在settings中的认证后端对象,代码如下:
def _get_backends(return_tuples=False):
backends = []
for backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
backends.append((backend, backend_path) if return_tuples else backend)
if not backends:
raise ImproperlyConfigured(
'No authentication backends have been defined. Does '
'AUTHENTICATION_BACKENDS contain anything?'
)
return backends
可以看到,对于定义在settings下的AUTHENTICATION_BACKENDS中的认证后端的路径(Django默认的AUTHENTICATION_BACKENDS内仅有一条'django.contrib.auth.backends.ModelBackend'
),会依次调用load_backend方法,代码如下:
def load_backend(path):
return import_string(path)
import_string方法定义在utils.module_loading.py中:
def import_string(dotted_path): """ Import a dotted module path and return the attribute/class designated by the last name in the path. Raise ImportError if the import failed. """ try: module_path, class_name = dotted_path.rsplit('.', 1) except ValueError as err: raise ImportError("%s doesn't look like a module path" % dotted_path) from err ## 对于的django自定义的AUTHENTICATION_BACKENDS: ## 'django.contrib.auth.backends.ModelBackend' ## module_path = 'django.contrib.auth.backends' ## class_name = 'ModelBackend' module = import_module(module_path) # 此时module就是backends模块 try: return getattr(module, class_name) # 返回定义在backends中的‘ModelBackend’类 except AttributeError as err: raise ImportError('Module "%s" does not define a "%s" attribute/class' % ( module_path, class_name) ) from err
所以默认情况下_get_backends最终返回的是[<class ‘django.contrib.auth.backends.ModelBackend’>],即一个类对象的列表。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。