Почему post_save создается дважды во время сохранения модели Django?

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

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

Быстрый пример, просто печать модели на консоль (с использованием сервера dev):

from blog.models import Post
from django.db.models import signals

def purge_cache(sender, **kwargs):
    print 'Purging %s' % sender

signals.post_save.connect(purge_cache, sender=Post)

Это использование стабильной версии 1.1.1 Django.

Обновленная информация:

С отзывами от всех комментариев, я изменил свой вопрос, потому что проблема теперь обнаруживает, почему post_save запускается дважды. На мой взгляд, в настоящий момент мой код models.py импортируется дважды и что post_save подключается несколько раз.

Что было бы лучшим способом выяснить, почему он импортируется/запускается дважды?

Ответы

Ответ 1

По-видимому, Python чувствителен к тому, как вы импортируете модули. В моем случае это не проблема с каким-либо кодом импорта внутри моего приложения в блоге, но проблема с конфигурацией INSTALLED_APPS, которую я предполагаю, используется Django для первоначального импорта.

В моем приложении для блогов я использовал импорт, например:

from blog.models import *

Мои параметры settings.py были настроены как:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    ...snip...
    'sorl.thumbnail',
    'mysite.blog',
)

Префикс "mysite" был добавлен, потому что изначально у меня возникли проблемы с пути импорта при развертывании сайта. Позже я исправил эту проблему (поэтому она действовала так же, как сервер разработки), добавив несколько путей в мой WSGI script.

Удаление префикса "mysite" из settings.py исправлено:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    ...snip...
    'sorl.thumbnail',
    'blog',
)

Ответ 2

При поиске корня этой проблемы вы можете использовать быстрое обходное решение для предотвращения регистрации сигнала дважды:

signals.post_save.connect(my_handler, MyModel, dispatch_uid="path.to.this.module")

Источник.

Ответ 3

Вот билет по этой проблеме: Структура сигнала Django может регистрировать слушателей более одного раза # 3951. Теперь он исправлен в версии SVN Django.

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