signals.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import os
  2. import time
  3. import threading
  4. import warnings
  5. from django.conf import settings
  6. from django.db import connections
  7. from django.dispatch import receiver, Signal
  8. from django.utils import timezone
  9. from django.utils.functional import empty
  10. template_rendered = Signal(providing_args=["template", "context"])
  11. setting_changed = Signal(providing_args=["setting", "value", "enter"])
  12. # Most setting_changed receivers are supposed to be added below,
  13. # except for cases where the receiver is related to a contrib app.
  14. # Settings that may not work well when using 'override_settings' (#19031)
  15. COMPLEX_OVERRIDE_SETTINGS = set(['DATABASES'])
  16. @receiver(setting_changed)
  17. def clear_cache_handlers(**kwargs):
  18. if kwargs['setting'] == 'CACHES':
  19. from django.core.cache import caches
  20. caches._caches = threading.local()
  21. @receiver(setting_changed)
  22. def update_installed_apps(**kwargs):
  23. if kwargs['setting'] == 'INSTALLED_APPS':
  24. # Rebuild any AppDirectoriesFinder instance.
  25. from django.contrib.staticfiles.finders import get_finder
  26. get_finder.cache_clear()
  27. # Rebuild management commands cache
  28. from django.core.management import get_commands
  29. get_commands.cache_clear()
  30. # Rebuild templatetags module cache.
  31. from django.template import base as mod
  32. mod.templatetags_modules = []
  33. # Rebuild app_template_dirs cache.
  34. from django.template.loaders import app_directories as mod
  35. mod.app_template_dirs = mod.calculate_app_template_dirs()
  36. # Rebuild translations cache.
  37. from django.utils.translation import trans_real
  38. trans_real._translations = {}
  39. @receiver(setting_changed)
  40. def update_connections_time_zone(**kwargs):
  41. if kwargs['setting'] == 'TIME_ZONE':
  42. # Reset process time zone
  43. if hasattr(time, 'tzset'):
  44. if kwargs['value']:
  45. os.environ['TZ'] = kwargs['value']
  46. else:
  47. os.environ.pop('TZ', None)
  48. time.tzset()
  49. # Reset local time zone cache
  50. timezone._localtime = None
  51. # Reset the database connections' time zone
  52. if kwargs['setting'] == 'USE_TZ' and settings.TIME_ZONE != 'UTC':
  53. USE_TZ, TIME_ZONE = kwargs['value'], settings.TIME_ZONE
  54. elif kwargs['setting'] == 'TIME_ZONE' and not settings.USE_TZ:
  55. USE_TZ, TIME_ZONE = settings.USE_TZ, kwargs['value']
  56. else:
  57. # no need to change the database connnections' time zones
  58. return
  59. tz = 'UTC' if USE_TZ else TIME_ZONE
  60. for conn in connections.all():
  61. conn.settings_dict['TIME_ZONE'] = tz
  62. tz_sql = conn.ops.set_time_zone_sql()
  63. if tz_sql:
  64. conn.cursor().execute(tz_sql, [tz])
  65. @receiver(setting_changed)
  66. def clear_context_processors_cache(**kwargs):
  67. if kwargs['setting'] == 'TEMPLATE_CONTEXT_PROCESSORS':
  68. from django.template import context
  69. context._standard_context_processors = None
  70. @receiver(setting_changed)
  71. def clear_template_loaders_cache(**kwargs):
  72. if kwargs['setting'] == 'TEMPLATE_LOADERS':
  73. from django.template import loader
  74. loader.template_source_loaders = None
  75. @receiver(setting_changed)
  76. def clear_serializers_cache(**kwargs):
  77. if kwargs['setting'] == 'SERIALIZATION_MODULES':
  78. from django.core import serializers
  79. serializers._serializers = {}
  80. @receiver(setting_changed)
  81. def language_changed(**kwargs):
  82. if kwargs['setting'] in {'LANGUAGES', 'LANGUAGE_CODE', 'LOCALE_PATHS'}:
  83. from django.utils.translation import trans_real
  84. trans_real._default = None
  85. trans_real._active = threading.local()
  86. if kwargs['setting'] in {'LANGUAGES', 'LOCALE_PATHS'}:
  87. from django.utils.translation import trans_real
  88. trans_real._translations = {}
  89. trans_real.check_for_language.cache_clear()
  90. @receiver(setting_changed)
  91. def file_storage_changed(**kwargs):
  92. if kwargs['setting'] in ('MEDIA_ROOT', 'DEFAULT_FILE_STORAGE'):
  93. from django.core.files.storage import default_storage
  94. default_storage._wrapped = empty
  95. @receiver(setting_changed)
  96. def complex_setting_changed(**kwargs):
  97. if kwargs['enter'] and kwargs['setting'] in COMPLEX_OVERRIDE_SETTINGS:
  98. # Considering the current implementation of the signals framework,
  99. # stacklevel=5 shows the line containing the override_settings call.
  100. warnings.warn("Overriding setting %s can lead to unexpected behavior."
  101. % kwargs['setting'], stacklevel=5)
  102. @receiver(setting_changed)
  103. def root_urlconf_changed(**kwargs):
  104. if kwargs['setting'] == 'ROOT_URLCONF':
  105. from django.core.urlresolvers import clear_url_caches
  106. clear_url_caches()