Created
September 27, 2011 17:04
-
-
Save EBNull/1245626 to your computer and use it in GitHub Desktop.
Changes prefix for admin templates based on request path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Before loading an admin template, it first modifies the template name based on the current thread's request url. | |
It will also fall back to the standard template name if themodified one is not found. | |
This uses a threadlocal hack. | |
settings.py: | |
MIDDLEWARE_CLASSES = ( | |
..., | |
'AdminTemplateRedirector.AdminTemplateRedirectorMiddleware', | |
... | |
) | |
TEMPLATE_LOADERS = ( | |
('AdminTemplateRedirector.AdminTemplateRedirector', ( | |
'django.template.loaders.filesystem.load_template_source', | |
'django.template.loaders.app_directories.load_template_source', | |
)), | |
) | |
#HACK: This should really be in the current urlconf | |
ADMIN_TEMPLATE_REDIR_MAP = { | |
'/newadmin/': 'newadmin/' | |
} | |
""" | |
from django.template.base import TemplateDoesNotExist | |
from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin | |
import django.template.loader | |
import threading | |
from django.conf import settings | |
from django.core.exceptions import MiddlewareNotUsed | |
_singleton = None | |
class AdminTemplateRedirectorMiddleware(object): | |
def __init__(self): | |
if not getattr(settings, 'ADMIN_TEMPLATE_REDIR_MAP'): | |
raise MiddlewareNotUsed | |
def _set_admin_template(self, template): | |
global _singleton | |
if _singleton is None: | |
#HACK: If we're the first request, the loader won't exist yet. This asks django to render something so that it does. | |
try: | |
django.template.loader.find_template('') | |
except Exception: | |
pass | |
if isinstance(_singleton, _AdminTemplateRedirectorClass): | |
_singleton.setthreadprefix(template) | |
def process_request(self, request): | |
t = 'admin/' | |
mapper = settings.ADMIN_TEMPLATE_REDIR_MAP | |
if callable(mapper): | |
t = mapper(request) | |
elif isinstance(mapper, dict): | |
for k, v in mapper.iteritems(): | |
if request.path_info.startswith(k): | |
t = v | |
break | |
self._set_admin_template(t) | |
def process_exception(self, request, exception): | |
self._set_admin_template(None) | |
def process_response(self, request, response): | |
self._set_admin_template(None) | |
return response | |
#HACK: Django will call this to create the loader | |
def AdminTemplateRedirector(*args, **kwargs): | |
global _singleton | |
if _singleton: | |
assert _singleton is None, "> 1 instance of AdminTemplateRedirector" | |
return _singleton | |
_singleton = _AdminTemplateRedirectorClass(*args, **kwargs) | |
return _singleton | |
AdminTemplateRedirector.load_template_source = True #HACK: Django hates functions apparently, this tricks it | |
class _AdminTemplateRedirectorClass(BaseLoader): | |
is_usable = True | |
def __init__(self, loaders): | |
self._loaders = loaders | |
self._cached_loaders = [] | |
self.local = threading.local() | |
def setthreadprefix(self, prefix): | |
self.local.adminprefix = prefix #needs to end with a slash | |
def getprefix(self): | |
return self.local.adminprefix | |
@property | |
def loaders(self): | |
# Resolve loaders on demand to avoid circular imports | |
if not self._cached_loaders: | |
for loader in self._loaders: | |
self._cached_loaders.append(find_template_loader(loader)) | |
return self._cached_loaders | |
def _modify_requested_templatespec(self, template_name, template_dirs=None): | |
modified = False | |
if template_name.startswith('admin/'): | |
template_name = self.getprefix() + template_name[6:] | |
modified = True | |
return template_name, template_dirs, modified | |
def find_template(self, oname, odirs=None): | |
n1, d1, modified = self._modify_requested_templatespec(oname, odirs) | |
for name, dirs in ((n1, d1), (oname, odirs)): | |
for loader in self.loaders: | |
try: | |
template, display_name = loader(name, dirs) | |
return (template, make_origin(display_name, loader, name, dirs)) | |
except TemplateDoesNotExist: | |
pass | |
raise TemplateDoesNotExist(name) | |
def load_template(self, template_name, template_dirs=None): | |
template, origin = self.find_template(template_name, template_dirs) | |
if not hasattr(template, 'render'): | |
try: | |
template = get_template_from_string(template, origin, template_name) | |
except TemplateDoesNotExist: | |
# If compiling the template we found raises TemplateDoesNotExist, | |
# back off to returning the source and display name for the template | |
# we were asked to load. This allows for correct identification (later) | |
# of the actual template that does not exist. | |
return template, origin | |
return template, origin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment