django.db.models.loading.get_model与导入

时间:2013-05-29 01:19:46

标签: django

使用像

这样的东西是否有任何缺点
from django.db.models.loading import get_model

def get_something():
    model = get_model('app', 'Model')
    return model.something()

而不是

from app.models import Model

def get_something():
    return Model.something()

第二个例子可以导致循环依赖,而第一个例子没有,但第二个例子更常见。

更新:如果第二个示例位于名为Other_Model的模型中,并且模型导入了Other_Model,则会出现循环依赖性错误 - 这是一个简单的循环导入。

2 个答案:

答案 0 :(得分:12)

通常,get_model功能保留用于需要动态加载模型的时间(例如,如果您不知道是否有人将服务传递给myapp.Person,myapp.Place,或者一个myapp.Thing,它们都有相同的界面)。我甚至会说,除非引入意外情况,否则任何其他用途都应该在代码审查中自动标记。

至于内部机制,确实没有实质性差异。 get_model版本不可避免地会调用__import__。那就是it is not without bugs。使用实际的import语句可以避免这个问题。


关于MRO问题,通过重构无法解决循环导入的罕见情况。如果你有两个相互依赖的应用程序导致循环导入,那么你真的需要重新考虑这些应用程序。 (我的猜测是你真的在处理一个应用程序。)

答案 1 :(得分:5)

如果您的应用路径不是那么直接,则使用get_model可能会造成混淆。

例如,如果您的模型存在于apps.MyApp.models.misc.MyModel中,那么调用将是get_model('MyApp', 'misc.MyModel'),这不是太直观。你可能不得不通过反复试验或深入研究来源来解决这个问题。

(请注意,这适用于Django 1.6及之前的版本.Django 1.7+对应用程序命名有很多变化,这可能已经改变了)


避免循环依赖的另一种方法是直接在方法中导入,如下所示:

def get_something():
    from app.models import Model
    return Model.something()

这将推迟导入,直到第一次调用方法。