Skip to content

Instantly share code, notes, and snippets.

@Kaelten
Created July 18, 2012 03:57
Show Gist options
  • Save Kaelten/3134075 to your computer and use it in GitHub Desktop.
Save Kaelten/3134075 to your computer and use it in GitHub Desktop.
from functools import wraps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse
from django.template.base import TemplateDoesNotExist
from django.template.context import RequestContext, Context
from django.template.loader import BaseLoader, find_template
from django.utils._os import safe_join
from django.utils.importlib import import_module
import os, re, sys
class AppSpecificLoader(BaseLoader):
is_usable = True
template_dirs = None
def get_template_sources(self, template_name, template_app=None):
if template_app is None:
# This block is a little bit of a hack in order to allow for the template-loader
# postmortems to work
matches = re.match(r"^app: ([^\s]+) template: ([^\s]+)$", template_name, re.S)
if matches is None:
yield template_name
template_app = matches.group(1)
template_name = matches.group(2)
if template_app in self.template_dirs:
try:
yield safe_join(self.template_dirs[template_app], template_name)
except UnicodeDecodeError:
raise
except ValueError:
pass
def populate_template_dirs(self):
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
self.template_dirs = {}
for app in settings.INSTALLED_APPS:
try:
module = import_module(app)
except ImportError, e:
raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
template_dir = os.path.join(os.path.dirname(module.__file__), 'templates')
if os.path.isdir(template_dir):
if '.' in app:
app = '.'.join(app.split('.')[1:])
self.template_dirs[app] = template_dir.decode(fs_encoding)
def load_template_source(self, template_name, template_app):
if self.template_dirs is None:
self.populate_template_dirs()
if template_app in self.template_dirs:
for template_path in self.get_template_sources(template_name, template_app):
try:
with open(template_path) as template:
return (template.read().decode(settings.FILE_CHARSET), template_path)
except IOError:
pass
raise TemplateDoesNotExist(template_name)
def find_specific_template(app, name):
try:
return find_template(name, app)
except TemplateDoesNotExist:
error_message ='app: {app} template: {template}'.format(app=app, template=name)
raise TemplateDoesNotExist(error_message)
def render_to_string(template_app, template_name, dictionary=None, context_instance=None):
if dictionary is None:
dictionary = {}
template, origin = find_specific_template(template_app, template_name)
if context_instance is None:
return template.render(Context(dictionary))
else:
context_instance.update(dictionary)
try:
return template.render(context_instance)
finally:
context_instance.pop()
def render_to_response(*args, **kwargs):
response_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
return HttpResponse(render_to_string(*args, **kwargs), **response_kwargs)
def using_template(app, template, mimetype=None):
def renderer(function):
@wraps(function)
def wrapper(request, *args, **kwargs):
context = function(request, *args, **kwargs)
return render_to_response(app, template, context,
context_instance=RequestContext(request), mimetype=mimetype)
return wrapper
return renderer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment