Add BaseSetting.for_request() to facilitate efficient repeat access of settings when accessed before rendering

pull/5932/head
Andy Babic 2020-02-14 10:34:12 +00:00
rodzic 3797132b4d
commit 255ad1f2a1
2 zmienionych plików z 38 dodań i 17 usunięć

Wyświetl plik

@ -9,24 +9,26 @@ class SettingsProxy(dict):
"""
Get a SettingModuleProxy for an app using proxy['app_label']
"""
def __init__(self, site):
self.site = site
def __init__(self, request_or_site):
self.request_or_site = request_or_site
def __missing__(self, app_label):
self[app_label] = value = SettingModuleProxy(self.site, app_label)
self[app_label] = value = SettingModuleProxy(self.request_or_site, app_label)
return value
def __str__(self):
return 'SettingsProxy'
return "SettingsProxy"
class SettingModuleProxy(dict):
"""
Get a setting instance using proxy['modelname']
"""
def __init__(self, site, app_label):
self.site = site
def __init__(self, request_or_site, app_label):
self.app_label = app_label
self.request_or_site = request_or_site
def __getitem__(self, model_name):
""" Get a setting instance for a model """
@ -46,19 +48,14 @@ class SettingModuleProxy(dict):
if Model is None:
return None
return Model.for_site(self.site)
if isinstance(self.request_or_site, Site):
return Model.for_site(self.request_or_site)
# Utilises cached value on request if set
return Model.for_request(self.request_or_site)
def __str__(self):
return 'SettingsModuleProxy({0})'.format(self.app_label)
def settings(request):
def _inner(request):
site = Site.find_for_request(request)
if site is None:
# find_for_request() can't determine the site
return {}
else:
return SettingsProxy(site)
return {'settings': SimpleLazyObject(lambda: _inner(request))}
return {"settings": SettingsProxy(request)}

Wyświetl plik

@ -22,7 +22,31 @@ class BaseSetting(models.Model):
@classmethod
def for_site(cls, site):
"""
Get an instance of this setting for the site.
Get or create an instance of this setting for the site.
"""
instance, created = cls.objects.get_or_create(site=site)
return instance
@classmethod
def for_request(cls, request):
"""
Get or create an instance of this model for the request,
and cache the result on the request for faster repeat access.
"""
attr_name = cls.get_cache_attr_name()
if hasattr(request, attr_name):
return getattr(request, attr_name)
site = Site.find_for_request(request)
site_settings = cls.for_site(site)
setattr(request, attr_name, site_settings)
return site_settings
@classmethod
def get_cache_attr_name(cls):
"""
Returns the name of the attribute that should be used to store
a reference to the fetched/created object on a request.
"""
return "_{}.{}".format(
cls._meta.app_label, cls._meta.model_name
).lower()