【发布时间】:2012-01-20 16:12:59
【问题描述】:
我有一个带有自定义表单字段的 Django 应用程序,其中一些在其构造函数中操作缓慢。我最近惊讶地发现,当 Django 本身启动时,甚至在用户执行需要在视图中显示该表单的操作之前,这些构造函数就被调用了。
为什么它们在服务器启动时被实例化?
例子:
urls.py:
from myapp.views import view1
...
url(r'^test$', view1.test),
views/view1.py:
class MyForm(ModelForm):
class Meta:
model = MyModel
field1 = MyChoiceField()
class MyChoiceField(ChoiceField):
def __init__(self, choices=(), required=True, widget=None, label=None,
initial=None, help_text=None, *args, **kwargs):
super(ChoiceField, self).__init__(required, widget, label, initial,
help_text, *args, **kwargs)
self.choices = [(m.id, m.name) for m in ReallyLargeTableModel.objects.all()]
如果我在该字段构造函数中设置断点,然后启动 Django,它会在我第一次请求任何页面时中断,即使相关视图不需要该表单或字段。堆栈跟踪返回到 urls.py 中的导入行。
这是因为我在 urls.py 中导入 view1,而不是导入 view1.test?
编辑:这不是 Django 特定的,这是一个说明行为的测试用例:
class Something():
def __init__(self):
print "Something __init__() called"
class UsesSomething():
field = Something()
如果您在交互式终端中运行它,它将打印“Something init() called”。这让我很惊讶,因为我实际上并没有实例化 UsesSomething 对象。
【问题讨论】:
-
老实说,从来没有真正关注过,因为它在我的应用程序中并不重要,但感觉不对。
__init__在类被实例化之前不应被调用。通常,该类实际上需要您必须提供的额外数据才能运行初始化。不过,如果您放弃导入视图而直接使用url(r'^test$', 'myapp.views.view1.test'),会发生什么?