有人可以解释一下这种行为:
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
),但我想知道发生了什么
答案 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识别这些两个不同的班级。