Skip to content

Instantly share code, notes, and snippets.

@EBNull
Created September 27, 2011 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EBNull/1245626 to your computer and use it in GitHub Desktop.
Save EBNull/1245626 to your computer and use it in GitHub Desktop.
Changes prefix for admin templates based on request path
"""
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