Код, который пытается получить доступ к моделям до их создания, в значительной степени может существовать только на уровне модуля; как показано в вашем примере, это должен быть исполняемый код, запускаемый при импорте модуля. Это, как вы уже догадались, причина в syncdb не работает. Он пытается импортировать модуль, но процесс импорта модуля вызывает выполнение кода уровня приложения; «побочный эффект», если хотите.
Желание избежать импорта модулей, вызывающих побочные эффекты, настолько сильно в Python, что соглашение if __name__ == '__main__':
для исполняемых скриптов Python стало обычным явлением. Когда простая загрузка библиотеки кода вызывает запуск приложения, возникают головные боли: -)
Для приложений Django это становится не просто головной болью. Рассмотрим эффект выполнения oldJob.delete()
каждый раз, когда модуль импортируется. Может показаться, что он выполняется только один раз при запуске с сервером разработки Django, но в производственной среде он будет выполняться довольно часто. Например, если вы используете Apache, Apache будет часто запускать несколько дочерних процессов, ожидающих обработки запросов. По мере продвижения долго работающего сервера ваше приложение Django будет загружаться каждый раз, когда обрабатывается обработчик для вашего веб-сервера, а это означает, что модуль будет импортирован и delete()
будет вызываться несколько раз, часто непредсказуемо. К сожалению, сигнал не поможет, так как сигнал может запускаться каждый раз, когда также запускается процесс Apache.
Между прочим, это не просто веб-сервер, который может привести к непреднамеренному выполнению вашего кода. Если вы используете такие инструменты, как epydoc, например, они будут импортировать ваш код для создания документации API. Это, в свою очередь, приведет к тому, что логика вашего приложения начнет выполняться, что, очевидно, является нежелательным побочным эффектом от запуска анализатора документации.
По этой причине подобный код очистки лучше всего обрабатывать заданием cron, которое периодически ищет устаревшие задания и очищает базу данных. Этот пользовательский сценарий также может быть запущен вручную или любым процессом (например, во время развертывания или как часть функции модульного теста setUp()
, чтобы обеспечить чистый тестовый запуск). Независимо от того, как вы это делаете, важно, чтобы такой код всегда выполнялся явно , а не неявно в результате открытия исходного файла.
Надеюсь, это поможет. Я знаю, что он не позволяет определить, запущен ли syncdb, но проблема с syncdb волшебным образом исчезнет, если вы создадите приложение Django с учетом развертывания в производственных условиях.