theme.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from django.conf import settings
  2. from django.utils.importlib import import_module
  3. from coffin.shortcuts import render_to_response
  4. from coffin.template import dict_from_django_context
  5. from coffin.template.loader import get_template, select_template, render_to_string
  6. '''Monkeypatch Django to mimic Jinja2 behaviour'''
  7. from django.utils import safestring
  8. if not hasattr(safestring, '__html__'):
  9. safestring.SafeString.__html__ = lambda self: str(self)
  10. safestring.SafeUnicode.__html__ = lambda self: unicode(self)
  11. class Theme(object):
  12. middlewares = ()
  13. def __init__(self, theme):
  14. self.set_theme(theme);
  15. if not self.middlewares:
  16. self.load_middlewares(settings.TEMPLATE_MIDDLEWARES)
  17. def load_middlewares(self, middlewares):
  18. for extension in middlewares:
  19. module = '.'.join(extension.split('.')[:-1])
  20. extension = extension.split('.')[-1]
  21. module = import_module(module)
  22. middleware = getattr(module, extension)
  23. self.middlewares += (middleware(), )
  24. def merge_contexts(self, dictionary=None, context_instance=None):
  25. dictionary = dictionary or {}
  26. if context_instance:
  27. context_instance.update(dictionary)
  28. else:
  29. context_instance = dictionary
  30. return context_instance
  31. def process_context(self, templates, context):
  32. for middleware in self.middlewares:
  33. try:
  34. new_context = middleware.process_context(self, templates, context)
  35. if new_context:
  36. context = new_context
  37. except AttributeError:
  38. pass
  39. return context
  40. def process_template(self, templates, context):
  41. for middleware in self.middlewares:
  42. try:
  43. new_templates = middleware.process_template(self, templates, context)
  44. if new_templates:
  45. return new_templates
  46. except AttributeError:
  47. pass
  48. return templates
  49. def set_theme(self, theme):
  50. if theme not in settings.INSTALLED_THEMES:
  51. raise ValueError('"%s" is not correct theme name.' % theme)
  52. if theme[0] == '_':
  53. raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
  54. self._theme = theme;
  55. def reset_theme(self):
  56. self._theme = settings.INSTALLED_THEMES[0]
  57. def get_theme(self):
  58. return self._theme
  59. def prefix_templates(self, templates, dictionary=None):
  60. templates = self.process_template(templates, dictionary)
  61. if isinstance(templates, str):
  62. return ('%s/%s' % (self._theme, templates), templates)
  63. else:
  64. prefixed = []
  65. for template in templates:
  66. prefixed.append('%s/%s' % (self._theme, template))
  67. prefixed += templates
  68. return prefixed
  69. def render_to_string(self, templates, dictionary=None, context_instance=None):
  70. dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
  71. templates = self.prefix_templates(templates, dictionary)
  72. return render_to_string(templates, dictionary)
  73. def render_to_response(self, templates, dictionary=None, context_instance=None,
  74. mimetype=None):
  75. dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
  76. templates = self.prefix_templates(templates, dictionary)
  77. return render_to_response(templates, dictionary=dictionary, mimetype=mimetype)
  78. def macro(self, templates, macro, dictionary={}, context_instance=None):
  79. templates = self.prefix_templates(templates, dictionary)
  80. template = select_template(templates)
  81. if context_instance:
  82. context_instance.update(dictionary)
  83. else:
  84. context_instance = dictionary
  85. context_instance = dict_from_django_context(context_instance)
  86. _macro = getattr(template.make_module(context_instance), macro)
  87. return unicode(_macro()).strip()
  88. def get_email_templates(self, template, contex={}):
  89. email_type_plain = '_email/%s.txt' % template
  90. email_type_html = '_email/%s.html' % template
  91. return (
  92. select_template(('%s/%s' % (self._theme, email_type_plain[1:]), email_type_plain)),
  93. select_template(('%s/%s' % (self._theme, email_type_html[1:]), email_type_html)),
  94. )