How does django convert string to modules

2020-08-09 19:31发布

I am trying to understand an other magic thing about django: it can convert strings to modules.

In settings.py, INSTALLED_APPS is declared like that:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
)

All it contains is strings. But django will convert those strings to modules and import them later.

I want to do be able to do the same thing. but i don't know how. I have a dictionary of renderer dispatcher in settings.py:

RESOUCE_RENDERER = {
    'video': 'video_player',
    'audio': 'audio_player', 
}

I want to use it later like this: RESOURCE_RENDERER['video'](MyVideo).

I cannot assign directly the function name(eg video_player) because it lives in a module that needs settings.py.

2条回答
女痞
2楼-- · 2020-08-09 19:40

Take a look in django.conf.__init__.py, but basically it uses importlib like so:

try:
    mod = importlib.import_module(self.SETTINGS_MODULE)
except ImportError, e:
    raise ImportError("Could not import settings '%s' 
               (Is it on sys.path? Does it have syntax errors?):
                %s" % (self.SETTINGS_MODULE, e))

# Settings that should be converted into tuples if they're mistakenly entered
# as strings.
tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")

Edit: At the request of the OP I've expanded the example and contributed some more below.

Now, suppose you had a list of functions in this module, defined in for example FUNCTIONS TO CALL, a list of functions. Then, you could call each like this:

ARGUMENTS = '()'

for FUNCTION in FUNCTIONS_TO_CALL:
    function_string = FUNCTION + ARGUMENTS
    exec(function_string)

This assumes each function has the same set of defined arguments. You could use an if statement to detect the function name listed by the user and supply custom arguments depending on what this is. You could also evaluate from reading the python file what the arguments should be.

You could also check the module object to (I assume this is possible, I don't know) see if that function exists before calling exec() or eval(). I don't know, again, if one can evaluate from the function object what arguments it takes. I suspect so, but this is a separate (possibly already answered?) question.

查看更多
我只想做你的唯一
3楼-- · 2020-08-09 19:54

Since Django 1.7 there is a simple function for this. For example:

from django.utils.module_loading import import_string
my_module = import_string('path.to.my_module')

You can also get classes from the module:

MyClass = import_string('path.to.my_module.MyClass')
查看更多
登录 后发表回答