Loading django/conf/__init__.py +6 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import time # Needed for Windows from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured from django.utils.datastructures import dict_merge from django.utils.functional import LazyObject, empty from django.utils import six Loading Loading @@ -77,6 +78,10 @@ class BaseSettings(object): elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, six.string_types): raise ValueError("The ALLOWED_INCLUDE_ROOTS setting must be set " "to a tuple, not a string.") elif (hasattr(self, name) and name.isupper() and isinstance(getattr(self, name), dict) and isinstance(value, dict)): # This allows defining only a partial dict to update a global setting value = dict_merge(getattr(self, name), value) object.__setattr__(self, name, value) Loading Loading @@ -144,7 +149,7 @@ class UserSettingsHolder(BaseSettings): from the module specified in default_settings (if possible). """ self.__dict__['_deleted'] = set() self.default_settings = default_settings self.__dict__['default_settings'] = default_settings def __getattr__(self, name): if name in self._deleted: Loading django/db/migrations/loader.py +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ class MigrationLoader(object): @classmethod def migrations_module(cls, app_label): if app_label in settings.MIGRATION_MODULES: if settings.MIGRATION_MODULES.get(app_label): return settings.MIGRATION_MODULES[app_label] else: app_package_name = apps.get_app_config(app_label).name Loading django/utils/datastructures.py +20 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,26 @@ class SortedDict(dict): self.keyOrder = [] def dict_merge(a, b): """ Utility to recursively merge two dicts, taking care not to overwrite subkeys (which would happen with dict.update), but keeping existing key including those from subdictionaries (optionally opted-out if a `_clear_defaults` key is present). Thanks Ross McFarland (https://www.xormedia.com/recursively-merge-dictionaries-in-python/) """ if b.get('_clear_defaults'): return copy.deepcopy(b) result = copy.deepcopy(a) for key, value in six.iteritems(b): if key in a and isinstance(result[key], dict): result[key] = dict_merge(result[key], value) else: result[key] = value return result class OrderedSet(object): """ A set which keeps the ordering of the inserted items. Loading docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,9 @@ Miscellaneous widget to allow more customization. The undocumented ``url_markup_template`` attribute was removed in favor of ``template_with_initial``. * When a dictionary setting is overridden in user settings, both dictionaries are merged by default. See :ref:`dictionary-settings`. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading docs/topics/settings.txt +26 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,32 @@ between the current settings file and Django's default settings. For more, see the :djadmin:`diffsettings` documentation. .. _dictionary-settings: Overriding dictionary settings ------------------------------ .. versionchanged:: 1.8 When defining a dictionary-type setting which has a non-empty value (see :setting:`CACHES` for example), you do not have to redefine all its keys. You can just define the keys differing from the default, and Django will simply merge your setting value with the default value. For example, if you define :setting:`CACHES` so:: CACHES = { 'special': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } then ``CACHES['default']`` which is set by default in Django's global settings will still be defined, as well as the new ``'special'`` cache backend. If you want your setting to completely override the default value, you can add a ``_clear_defaults`` key with a ``True`` value to the dictionary. Using settings in Python code ============================= Loading Loading
django/conf/__init__.py +6 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import time # Needed for Windows from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured from django.utils.datastructures import dict_merge from django.utils.functional import LazyObject, empty from django.utils import six Loading Loading @@ -77,6 +78,10 @@ class BaseSettings(object): elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, six.string_types): raise ValueError("The ALLOWED_INCLUDE_ROOTS setting must be set " "to a tuple, not a string.") elif (hasattr(self, name) and name.isupper() and isinstance(getattr(self, name), dict) and isinstance(value, dict)): # This allows defining only a partial dict to update a global setting value = dict_merge(getattr(self, name), value) object.__setattr__(self, name, value) Loading Loading @@ -144,7 +149,7 @@ class UserSettingsHolder(BaseSettings): from the module specified in default_settings (if possible). """ self.__dict__['_deleted'] = set() self.default_settings = default_settings self.__dict__['default_settings'] = default_settings def __getattr__(self, name): if name in self._deleted: Loading
django/db/migrations/loader.py +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ class MigrationLoader(object): @classmethod def migrations_module(cls, app_label): if app_label in settings.MIGRATION_MODULES: if settings.MIGRATION_MODULES.get(app_label): return settings.MIGRATION_MODULES[app_label] else: app_package_name = apps.get_app_config(app_label).name Loading
django/utils/datastructures.py +20 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,26 @@ class SortedDict(dict): self.keyOrder = [] def dict_merge(a, b): """ Utility to recursively merge two dicts, taking care not to overwrite subkeys (which would happen with dict.update), but keeping existing key including those from subdictionaries (optionally opted-out if a `_clear_defaults` key is present). Thanks Ross McFarland (https://www.xormedia.com/recursively-merge-dictionaries-in-python/) """ if b.get('_clear_defaults'): return copy.deepcopy(b) result = copy.deepcopy(a) for key, value in six.iteritems(b): if key in a and isinstance(result[key], dict): result[key] = dict_merge(result[key], value) else: result[key] = value return result class OrderedSet(object): """ A set which keeps the ordering of the inserted items. Loading
docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,9 @@ Miscellaneous widget to allow more customization. The undocumented ``url_markup_template`` attribute was removed in favor of ``template_with_initial``. * When a dictionary setting is overridden in user settings, both dictionaries are merged by default. See :ref:`dictionary-settings`. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading
docs/topics/settings.txt +26 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,32 @@ between the current settings file and Django's default settings. For more, see the :djadmin:`diffsettings` documentation. .. _dictionary-settings: Overriding dictionary settings ------------------------------ .. versionchanged:: 1.8 When defining a dictionary-type setting which has a non-empty value (see :setting:`CACHES` for example), you do not have to redefine all its keys. You can just define the keys differing from the default, and Django will simply merge your setting value with the default value. For example, if you define :setting:`CACHES` so:: CACHES = { 'special': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } then ``CACHES['default']`` which is set by default in Django's global settings will still be defined, as well as the new ``'special'`` cache backend. If you want your setting to completely override the default value, you can add a ``_clear_defaults`` key with a ``True`` value to the dictionary. Using settings in Python code ============================= Loading