动态加载模块后对加载模块使用"from x import *

3 投票
1 回答
777 浏览
提问于 2025-04-16 02:04

我有一些Django应用程序,它们是根据应用名称来区分版本的。

比如说:appv1 和 appv2。

这些应用里的models.py文件根据版本的不同稍有不同,但模型名称是一样的。

我想动态加载这些模型到当前的命名空间里。

所以我写了一个函数,试图获取模块并返回它:

def get_models_module(release):
    release_models_path = u"project.data_%s" % (release)
    _temp = __import__(release_models_path, globals(), locals(), ["models"], -1)
    models = _temp.models
    return models

然后我尝试从返回的模型模块中加载所有模型,但失败了。

models = get_models_module("1")
from models import *

出现这种情况时,我收到了一个错误:

ImportError: No module named models

我检查了一下,返回的“models”对象显示为“module 'project.data_1.models' ...”,但显然它不喜欢被重命名。

有没有办法让我从特定的应用版本中加载所有定义的模型?或者,有没有更好的方法来处理这种情况?

注意:这目前只是在加载函数中用来将数据放入数据库,并没有通过任何视图运行。


更新的解决方案:

感谢Daniel Kluev提供的解决方案,这是我更新后的函数:

def load_release_models(release):
    model_release = release.replace(u".", u"_").replace(u"-", u"d") 
    release_models_path = u"project.data_%s.models" % (model_release)
    # import all release models into (global) namespace
    exec(u"from {0} import *".format(release_models_path)) in globals()

注意 - 我将模型加载到全局变量中,因为我需要在整个文件中访问这些模型。

1 个回答

4

from models import * 这行代码中,你并不是在指代一个叫 models 的变量。你实际上是在尝试导入一个名为 'models' 的模块,但显然这个模块并不存在。

你可以用一些小技巧把模块里的所有内容导入到当前的命名空间中:

ldict = locals()
for k in models.__dict__:
    if not k.startswith('__') or not k.endswith('__'):
        ldict[k] = models.__dict__[k]

或者你可以使用 exec() 来加载这个模块,

exec("from project.data_{0}.models import *".format(release)) in locals()

撰写回答