Почему при запуске Django вызываются методы поля формы __init__? - PullRequest
2 голосов
/ 20 января 2012

У меня есть приложение 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.

Это потому, что я импортирую view1 в urls.py вместо импорта view1.test?

Редактировать: Это не специфично для Django, вот тестовый пример, иллюстрирующий поведение:

class Something():
    def __init__(self):
        print "Something __init__() called"

class UsesSomething():
    field = Something()

Если вы запустите его в интерактивном терминале, оннапечатает "Нечто init () вызвано".Это меня удивило, потому что я на самом деле не создал объект UsesSomething.

Ответы [ 2 ]

8 голосов
/ 20 января 2012

Поскольку вы создаете экземпляры полей в определении формы, которое предположительно импортируется одним из ваших представлений.

Поле init является неподходящим местом для такой динамической инициализации по этой точной причине.Вы хотите что-то, что вызывается, когда форма инициализируется: то есть форма __init__.

Тем не менее, на самом деле вы вообще не хотите этого делать - вам просто нужно использовать forms.ModelChoiceFieldкоторый принимает набор запросов и выполняет динамическое назначение вариантов выбора.

class MyForm(ModelForm):
    field1 = forms.ModelChoiceField(queryset=ReallyLargeTableModel.objects.all())
0 голосов
/ 20 января 2012

В вашем примере:

class UsesSomething():
    field = Something()

Строка кода field = Something() будет выполняться, когда вы импортируете содержащий модуль, когда Python обрабатывает определение класса.Вот как работает Python.Вы можете фактически поместить произвольный код в определение класса.

module: test.py:

class UsesSomething():
    print "wow!"

>>> import test
wow!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...