【问题标题】:Django signal only works when debug=True, DJANGO 3.2.4Django 信号仅在 debug=True 时有效,DJANGO 3.2.4
【发布时间】:2021-10-30 07:58:27
【问题描述】:

我一直在到处寻找,但找不到任何关于此的参考,我的 Django 模型信号仅在 debug=True 时有效,但在 debug=False 时不起作用,这在 localhost 和生产中都发生服务器。

我的设置如下所示:

settings.py

from pathlib import Path
import os
import environ

env = environ.Env()

environ.Env.read_env()

BASE_DIR = Path(__file__).resolve().parent.parent

#production
STATIC_ROOT = 'https://d1u356tnw52tcs.cloudfront.net/'


SECRET_KEY = env("SECRET_KEY_PROD")

DEBUG = True

ALLOWED_HOSTS = ['*']

CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
)


# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'django.contrib.postgres',
    'sellrapp',
    'stock_management',
    'corsheaders',
    'drf_yasg',
    'optimized_image',
    'csvexport',
    'kronos',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware'
]

ROOT_URLCONF = '****.urls'


WSGI_APPLICATION = '****.wsgi.application'


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': env("NAME_PROD"),
        'USER': env("USER_PROD"),
        'PASSWORD': env("PASSWORD_PROD"),
        'HOST': env("HOST_PROD"),
        'PORT': env("PORT_PROD"),
    }
}

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Singapore'

USE_I18N = True

USE_L10N = True

USE_TZ = True


WEB_BASE_URL = 'https://****.com/'
BASE_URL_LIVE_CAMPAIGN = WEB_BASE_URL + "product/"

如果设置为 debug=False,则不会触发信号,也不会出现任何错误。

信号.py

from django.dispatch import receiver
from django.db.models.signals import pre_save, post_save, pre_delete
from .models import ManualWithdrawals


@receiver(pre_delete, sender=ManualWithdrawals)
def manual_wd(sender, instance, **kwargs):
    order = ManualWithdrawals.objects.get(id=instance.id)
    consumer_order = order.order_id_list.all()
    sample_order = order.sample_order_id_list.all()
    total = str(instance.total_withdrawals).replace(".", "")
    total = int(total)
    if instance.order_id_list:
        for order in consumer_order:
            if instance.type == "reseller" and order.reseller_commission_status != "paid":
                order.reseller_commission_status = "ready for collection"
                order.save()
            if instance.type == "merchant" and order.merchant_commission_status != "paid":
                order.merchant_commission_status = "ready for collection"
                order.save()
        # updating sample order if any
    if instance.sample_order_id_list:
        for order in sample_order:
            if instance.type == "merchant" and order.merchant_commission_status != "paid":
                order.merchant_commission_status = "ready for collection"
                order.save()

【问题讨论】:

  • 您能否尝试任何其他信号,例如 pre_save 以查看它是否正常工作,以便我们确认这是项目级别的问题,而不是特定于该信号?
  • pre_save 并且所有方法也不起作用......是否有可能因为我正在使用 django-environ.readthedocs.io/en/latest/# ? @cmkishores
  • 面临同样的问题。有人找到解决办法了吗?

标签: django django-models django-signals


【解决方案1】:

事实证明,当我更新到 psycopg 的新版本时出现问题,不知何故,在将我的 psycopg 更新到最新版本之后,现在它工作得很好。

【讨论】:

  • 你用的是什么版本?
  • 抱歉,更新到最新版本的 psycopg 对我不起作用
【解决方案2】:

这对我有用:

在调用信号的connect()@receiver 时传递weak=False。


Django Signals 提及警告:

另请注意,Django 默认将信号处理程序存储为弱引用,因此如果您的处理程序是本地函数,它可能会被垃圾回收。为防止这种情况,请在调用信号的 connect() 时传递 weak=False。

因此,您的接收器函数可能正在被垃圾收集。

例如,尝试使用:@receiver(pre_delete, sender=ManualWithdrawals, weak=False)

【讨论】:

    【解决方案3】:

    只是为@kaustubh-trivei 答案添加更多见解。

    当处理程序以这种方式注册时:

    from django.db.models.signals import post_save
    
    def create_and_register_handler(model):
        def handler(sender, instance=None, created=False, **kwargs):
            ...
    
        post_save.connect(handler, sender=model)
    

    那么weak=False 是强制性的,否则它会立即被垃圾回收和注销。

    由于实现细节,当settings.DEBUGTrue 时,Django 会为处理程序创建一个额外的引用,以防止处理程序被垃圾收集和注销。

    实现细节:当settings.DEBUGTrue 时,处理程序的参数由django.utils.inspect 模块验证,该模块在内部使用functools.lru_cache() 装饰器,这导致处理程序作为键存储在lru 缓存字典中。

    【讨论】:

      猜你喜欢
      • 2021-01-03
      • 2014-11-06
      • 2018-08-22
      • 1970-01-01
      • 2017-10-28
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 2011-11-16
      相关资源
      最近更新 更多