Вопрос

У меня есть некоторый код, который выдает ошибку syncdb (потому что он пытается получить доступ к модели до создания таблиц).

Есть ли способ предотвратить запуск кода в syncdb?что -то вроде:

if not syncdb:
    run_some_code()

Спасибо :)

Редактировать:PS - Я думал об использовании сигнала post_init...для кода, который обращается к базе данных, это хорошая идея?

Подробная информация

Вот еще немного информации по запросу :)

Например, я сталкивался с этим пару раз...Я взламывал django-cron и решил, что необходимо убедиться, что при загрузке django отсутствуют существующие задания (потому что он ищет задания во всех установленных приложениях и все равно добавляет их при загрузке).

Итак, я добавил следующий код в верхнюю часть __init__.py файл:

import sqlite3

try:
        # Delete all the old jobs from the database so they don't interfere with this instance of django
        oldJobs = models.Job.objects.all()
        for oldJob in oldJobs:
                oldJob.delete()
except sqlite3.OperationalError:
        # When you do syncdb for the first time, the table isn't 
        # there yet and throws a nasty error... until now
        pass

По очевидным причинам это чушь собачья.это привязано к sqlite, и я уверен, что есть лучшие места для размещения этого кода (именно так я и столкнулся с проблемой), но это работает.

Как вы можете видеть, ошибка, которую вы получаете, является операционной ошибкой (в sqlite), и трассировка стека говорит что-то вроде "таблица django_cron_job не найдена".

Решение

В конце концов, цель состояла в том, чтобы запустите некоторый код перед загрузкой каких-либо страниц.

Этого можно достичь, выполнив его в файле urls.py, поскольку он должен быть импортирован до того, как страница может быть отправлена (очевидно).

И я смог удалить этот уродливый блок try / except :) Слава богу (и S.Лотт)

Это было полезно?

Решение

"редактировать:PS - Я думал об использовании сигнала post_init...для кода, который обращается к базе данных, это хорошая идея?"

Никогда.

Если у вас есть код, который обращается к модели до создания таблиц, у вас возникают большие-пребольшие проблемы.Вероятно, вы делаете что-то серьезно неправильное.

Обычно вы запускаете syncdb примерно один раз.База данных создана.И ваше веб-приложение использует базу данных.

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

Вам (как правило) не нужен код в __init__.py модуль.У вас (почти) никогда не должно быть исполняемого кода, который выполняет реальную работу в __init__.py модуль.Это очень, очень редко и неуместно для Django.

Я не совсем понимаю, зачем ты связываешься со __init__.py когда Django Cron ( Джанго Хрон) говорит, что вы договариваетесь о своем расписании в urls.py.


Редактировать

Очистка записей - это одно.

Возиться с __init__.py и Django-cron's base.py очевидно, что это совершенно неправильные способы сделать это.Если это так сложно, значит, вы делаете это неправильно.

Невозможно сказать, что вы пытаетесь сделать, но это должно быть тривиально.

Ваш urls.py может запускаться только после syncdb и после того, как весь материал ORM был правильно настроен и привязан.

Ваш urls.py можно, например, удалить некоторые строки, а затем добавить несколько строк в таблицу.На данный момент все проблемы с syncdb устранены.

Почему у тебя нет своей логики в urls.py?

Другие советы

Код, который пытается получить доступ к моделям до их создания, в значительной степени может существовать только на уровне модуля;это должен быть исполняемый код, запускаемый при импорте модуля, как показано в вашем примере.Это, как вы уже догадались, причина сбоя syncdb.Он пытается импортировать модуль, но процесс импорта модуля приводит к выполнению кода уровня приложения;"побочный эффект", если хотите.

Желание избежать импорта модулей, вызывающих побочные эффекты, настолько сильно в Python, что if __name__ == '__main__': соглашение для исполняемых скриптов python стало обычным делом.Когда простая загрузка библиотеки кода приводит к запуску приложения, возникают головные боли :-)

Для приложений Django это становится больше, чем головной болью.Рассмотрим эффект от наличия oldJob.delete() выполняется каждый раз, когда модуль импортируется.Может показаться, что он выполняется только один раз, когда вы запускаетесь с сервером разработки Django, но в производственной среде он будет выполняться довольно часто.Например, если вы используете Apache, Apache часто запускает несколько дочерних процессов, ожидающих обработки запросов.По мере работы сервера с длительной загрузкой ваше приложение Django будет загружаться каждый раз, когда для вашего веб-сервера разветвляется обработчик, что означает, что модуль будет импортирован и delete() будет вызван несколько раз, часто непредсказуемо.Сигнал, к сожалению, не поможет, так как сигнал также может запускаться каждый раз при инициализации процесса Apache.

Кстати, это не просто веб-сервер, который может привести к непреднамеренному выполнению вашего кода.Например, если вы используете такие инструменты, как epydoc, они импортируют ваш код для создания документации API.Это, в свою очередь, приведет к запуску логики вашего приложения, что, очевидно, является нежелательным побочным эффектом простого запуска анализатора документации.

По этой причине подобный код очистки лучше всего обрабатывается заданием cron, которое периодически ищет устаревшие задания и очищает базу данных.Этот пользовательский скрипт также может быть запущен вручную или любым процессом (например, во время развертывания или как часть вашего модульного теста setUp() функция для обеспечения чистого тестового запуска).Независимо от того, как вы это делаете, важным моментом является то, что подобный код всегда должен выполняться явно, а не неявно в результате открытия исходного файла.

Я надеюсь, что это поможет.Я знаю, что это не дает способа определить, запущена ли syncdb, но проблема с syncdb волшебным образом исчезнет, если вы разработаете свое приложение Django с учетом производственного развертывания.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top