_theme.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. self._mutex = None
  16. if not self.middlewares:
  17. self.load_middlewares(settings.TEMPLATE_MIDDLEWARES)
  18. def load_middlewares(self, middlewares):
  19. for extension in middlewares:
  20. module = '.'.join(extension.split('.')[:-1])
  21. extension = extension.split('.')[-1]
  22. module = import_module(module)
  23. middleware = getattr(module, extension)
  24. self.middlewares += (middleware(), )
  25. def merge_contexts(self, dictionary=None, context_instance=None):
  26. dictionary = dictionary or {}
  27. if context_instance:
  28. context_instance.update(dictionary)
  29. else:
  30. context_instance = dictionary
  31. return context_instance
  32. def process_context(self, templates, context):
  33. if self._mutex:
  34. return context
  35. self._mutex = True
  36. for middleware in self.middlewares:
  37. try:
  38. new_context = middleware.process_context(self, templates, context)
  39. if new_context:
  40. context = new_context
  41. except AttributeError:
  42. pass
  43. self._mutex = None
  44. return context
  45. def process_template(self, templates, context):
  46. for middleware in self.middlewares:
  47. try:
  48. new_templates = middleware.process_template(self, templates, context)
  49. if new_templates:
  50. return new_templates
  51. except AttributeError:
  52. pass
  53. return templates
  54. def set_theme(self, theme):
  55. if theme not in settings.INSTALLED_THEMES:
  56. raise ValueError('"%s" is not correct theme name.' % theme)
  57. if theme[0] == '_':
  58. raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
  59. self._theme = theme;
  60. def reset_theme(self):
  61. self._theme = settings.INSTALLED_THEMES[0]
  62. def get_theme(self):
  63. return self._theme
  64. def prefix_templates(self, templates, dictionary=None):
  65. templates = self.process_template(templates, dictionary)
  66. if isinstance(templates, str):
  67. return ('%s/%s' % (self._theme, templates), templates)
  68. else:
  69. prefixed = []
  70. for template in templates:
  71. prefixed.append('%s/%s' % (self._theme, template))
  72. prefixed += templates
  73. return prefixed
  74. def render_to_string(self, templates, dictionary=None, context_instance=None):
  75. dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
  76. templates = self.prefix_templates(templates, dictionary)
  77. return render_to_string(templates, dictionary)
  78. def render_to_response(self, templates, dictionary=None, context_instance=None,
  79. mimetype=None):
  80. dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
  81. templates = self.prefix_templates(templates, dictionary)
  82. return render_to_response(templates, dictionary=dictionary, mimetype=mimetype)
  83. def macro(self, templates, macro, dictionary={}, context_instance=None):
  84. templates = self.prefix_templates(templates, dictionary)
  85. template = select_template(templates)
  86. if context_instance:
  87. context_instance.update(dictionary)
  88. else:
  89. context_instance = dictionary
  90. context_instance = dict_from_django_context(context_instance)
  91. _macro = getattr(template.make_module(context_instance), macro)
  92. return unicode(_macro()).strip()
  93. def get_email_templates(self, template, contex={}):
  94. email_type_plain = '_email/%s.txt' % template
  95. email_type_html = '_email/%s.html' % template
  96. return (
  97. select_template(('%s/%s' % (self._theme, email_type_plain[1:]), email_type_plain)),
  98. select_template(('%s/%s' % (self._theme, email_type_html[1:]), email_type_html)),
  99. )