繁体   English   中英

为什么在Django启动时调用表单字段__init__方法?

[英]Why are form field __init__ methods being called on Django startup?

我有一个带有自定义表单字段的Django应用程序,其中一些在构造函数中运行缓慢。 最近我惊讶地发现,当Django本身启动时,那些构造函数会被调用,甚至在用户在视图中执行需要该表单的操作之前。

为什么他们在服务器启动时被实例化?

例:

urls.py:

from myapp.views import view1
...
url(r'^test$', view1.test),

意见/ 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,它会在我第一次请求任何页面时中断,即使所讨论的视图不需要该表单或字段。 stacktrace返回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是进行这种动态初始化的错误位置。 你想要在初始化表单时调用的东西:即表单的__init__

也就是说,你根本不想这样做 - 你只需要使用forms.ModelChoiceField ,它接受一个查询集并为你做动态的选择。

class MyForm(ModelForm):
    field1 = forms.ModelChoiceField(queryset=ReallyLargeTableModel.objects.all())

在你的例子中:

class UsesSomething():
    field = Something()

当Python处理类定义时导入包含模块时,代码行field = Something()将执行。 这就是Python的工作原理。 实际上,您可以将任意代码放在类定义中。

module:test.py:

class UsesSomething():
    print "wow!"

>>> import test
wow!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM