Opened 7 years ago
Closed 7 years ago
#29079 closed Bug (wontfix)
Django settings should not cache user wrapped settings
Reported by: | Riccardo Di Virgilio | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 1.11 |
Severity: | Normal | Keywords: | |
Cc: | Adam Johnson | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
django 2.0 and 1.11 are breaking my custom settings.
I'm using settings.configure with a custom object that can change his properties if the environment is changing.
Starting from 1.11 the function LazySettings.__getattr__
is caching the values that are returned from the custom object that is provided by the user.
If all the custom object can do is to provide static values why I should use a custom object at all instead of a regular module?
In my view is an user needs to use a custom object as settings is because he needs advanced features that cannot be archived by a normal module.
It's very easy to add cache to all properties in a custom object if this is behavior the user needs, but is really hard to disable this (if not impossibile for the way this code is written).
If the staff is strongly against disabling the cache by default, can we at least add an option to disable it?
thanks.
Change History (5)
comment:1 by , 7 years ago
comment:2 by , 7 years ago
right ok this is a basic example:
from django.conf import settings class CustomSettings(object): ENVIRONMENT = "production" @property def DEFAULT_FROM_EMAIL(self): if self.ENVIRONMENT == "production": return "info@company.com" return "my-personal-email@gmail.com" obj = CustomSettings() settings.configure(obj) print(settings.DEFAULT_FROM_EMAIL, obj.DEFAULT_FROM_EMAIL) obj.ENVIRONMENT = settings.ENVIRONMENT = "development" print(settings.DEFAULT_FROM_EMAIL, obj.DEFAULT_FROM_EMAIL)
the output of this code on django 2.1 is :
info@company.com info@company.com info@company.com my-personal-email@gmail.com
my claim is that this property should be computer each time is accessed.
is true that django documentation says that you cannot expect runtime mutations to work and propagate properly trough django framework, but still internally I do rely on this behavior: I have internal settings that are generated for different environments and when I deploy django on production i'm deploying the settings by mutating the environment string and computing all properties.
this cannot be done anymore with the new behavior.
comment:3 by , 7 years ago
Cc: | added |
---|---|
Type: | Uncategorized → Bug |
The change in behavior is due to #27625 (c1b221a9b913315998a1bcec2f29a9361a74d1ac). I doubt we'll revert the change to restore an undocumented behavior but I'll cc Adam, the author of that change, for his input.
comment:4 by , 7 years ago
Yeah I don't think we should revert as it makes all settings access faster, noticeably so, as benchmarked by Instagram.
You could always set the setting to an object with dynamic behaviour on access e.g.
class DefaultFromEmail: def __str__(self): if settings.ENVIRONMENT == 'production': return 'info@company.com' return 'my-personal-email@gmail.com' DEFAULT_FROM_EMAIL = DefaultFromEmail()
Or use the undocumented, but unlikely to change, django.utils.functional.SimpleLazyObject
comment:5 by , 7 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
You should include a sample project or steps to reproduce the issue. Ideally, you could also bisect to find the commit where the behavior changed.