奇怪的django导入行为

时间:2011-06-16 11:32:56

标签: python django

有人可以解释一下这种行为:

django项目名为foo

档案bar/models.py

class MyModelError(TypeError):
    pass

class MyModel(models.Model):
    ...

./manage.py shell

>>> from foo.bar.models import MyModel as m1
>>> from bar.models import MyModel as m2
>>> from foo.bar.models import MyModelError as e1
>>> from bar.models import MyModelError as e2
>>> m1 is m2
True
>>> e1 is e2
False

假?!

>>> m1
<class 'foo.bar.models.MyModel'>
>>> m2
<class 'foo.bar.models.MyModel'>
>>> e1
<class 'foo.bar.models.MyModelError'>
>>> e1
<class 'bar.models.MyModelError'>

我在这里做错了什么?我的解决方法(除了确保我导入'正确的方法')是使错误类成为模型本身的成员(如django model.DoesNotExists),但我想知道发生了什么

2 个答案:

答案 0 :(得分:4)

Django使用元类来定义模型。有一个检查以避免定义模型两次,所以当创建一个类(如果它已经定义)然后你得到之前定义的版本。见django.db.models.base.ModelBase

from django.db.models.loading import get_model

# Bail out early if we have already created this class.
m = get_model(new_class._meta.app_label, name, False)
if m is not None:
    return m

虽然Error类是常规的Python类,并且没有这样的缓存,但是你会得到不同的版本,因为它们所属的模块是不同的。我认为这种情况会发生,因为在运行Django runserver时,您会以两种方式从路径加载相同的模块:

  • 当前目录
  • 当前目录上方的目录

这样您就可以导入完全限定的包(包括项目名称)并使其有效。

我倾向于永远不会使用项目名称导入以避免此问题。

答案 1 :(得分:0)

在大多数编程语言中,错误挂起具有类似阶梯的机制。因此,如果发生错误,异常机制将开始搜索异常以处理错误。如果在该类中无法处理异常,它会通过派生该类的类来保持搜索上层......它使这个过程保持在继承的最高层......

因此,您要定义从 TypeError 派生的 ModelError 类,并从不同路径导入该类可能会导致python interpereter识别这些两个不同的班级。

Python Documentation