当前位置:   article > 正文

Python importlib.import_module方法以及在Django中的使用

Python importlib.import_module方法以及在Django中的使用

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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

现在可以根据配置文件导入应用中:

>>> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

可以看到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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到,对于定义在settings下的AUTHENTICATION_BACKENDS中的认证后端的路径(Django默认的AUTHENTICATION_BACKENDS内仅有一条'django.contrib.auth.backends.ModelBackend'),会依次调用load_backend方法,代码如下:

def load_backend(path):
    return import_string(path)
  • 1
  • 2

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

所以默认情况下_get_backends最终返回的是[<class ‘django.contrib.auth.backends.ModelBackend’>],即一个类对象的列表。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/524405
推荐阅读
相关标签
  

闽ICP备14008679号