Browse Source

Refactored Misago to use django-like API, added thread._local singleton. #147

Ralfp 12 years ago
parent
commit
240648b7ef

+ 0 - 117
misago/_theme.py

@@ -1,117 +0,0 @@
-from django.conf import settings
-from django.utils.importlib import import_module
-from coffin.shortcuts import render_to_response
-from coffin.template import dict_from_django_context
-from coffin.template.loader import get_template, select_template, render_to_string
-
-'''Monkeypatch Django to mimic Jinja2 behaviour'''
-from django.utils import safestring
-if not hasattr(safestring, '__html__'):
-    safestring.SafeString.__html__ = lambda self: str(self)
-    safestring.SafeUnicode.__html__ = lambda self: unicode(self)
-
-class Theme(object):
-    middlewares = ()
-
-    def __init__(self, theme):
-        self.set_theme(theme);
-        self._mutex = None
-
-        if not self.middlewares:
-            self.load_middlewares(settings.TEMPLATE_MIDDLEWARES)
-
-    def load_middlewares(self, middlewares):
-        for extension in middlewares:
-            module = '.'.join(extension.split('.')[:-1])
-            extension = extension.split('.')[-1]
-            module = import_module(module)
-            middleware = getattr(module, extension)
-            self.middlewares += (middleware(), )
-
-    def merge_contexts(self, dictionary=None, context_instance=None):
-        dictionary = dictionary or {}
-        if context_instance:
-            context_instance.update(dictionary)
-        else:
-            context_instance = dictionary
-        return context_instance
-
-    def process_context(self, templates, context):
-        if self._mutex:
-            return context
-        self._mutex = True
-
-        for middleware in self.middlewares:
-            try:
-                new_context = middleware.process_context(self, templates, context)
-                if new_context:
-                    context = new_context
-            except AttributeError:
-                pass
-
-        self._mutex = None
-        return context
-
-    def process_template(self, templates, context):
-        for middleware in self.middlewares:
-            try:
-                new_templates = middleware.process_template(self, templates, context)
-                if new_templates:
-                    return new_templates
-            except AttributeError:
-                pass
-        return templates
-
-    def set_theme(self, theme):
-        if theme not in settings.INSTALLED_THEMES:
-            raise ValueError('"%s" is not correct theme name.' % theme)
-        if theme[0] == '_':
-            raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
-        self._theme = theme;
-
-    def reset_theme(self):
-        self._theme = settings.INSTALLED_THEMES[0]
-
-    def get_theme(self):
-        return self._theme
-
-    def prefix_templates(self, templates, dictionary=None):
-        templates = self.process_template(templates, dictionary)
-        if isinstance(templates, str):
-            return ('%s/%s' % (self._theme, templates), templates)
-        else:
-            prefixed = []
-            for template in templates:
-                prefixed.append('%s/%s' % (self._theme, template))
-            prefixed += templates
-            return prefixed
-
-    def render_to_string(self, templates, dictionary=None, context_instance=None):
-        dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
-        templates = self.prefix_templates(templates, dictionary)
-        return render_to_string(templates, dictionary)
-
-    def render_to_response(self, templates, dictionary=None, context_instance=None,
-                       mimetype=None):
-        dictionary = self.process_context(templates, self.merge_contexts(dictionary, context_instance))
-        templates = self.prefix_templates(templates, dictionary)
-        return render_to_response(templates, dictionary=dictionary, mimetype=mimetype)
-
-    def macro(self, templates, macro, dictionary={}, context_instance=None):
-        templates = self.prefix_templates(templates, dictionary)
-        template = select_template(templates)
-        if context_instance:
-            context_instance.update(dictionary)
-        else:
-            context_instance = dictionary
-        context_instance = dict_from_django_context(context_instance)
-        _macro = getattr(template.make_module(context_instance), macro)
-        return unicode(_macro()).strip()
-
-    def get_email_templates(self, template, contex={}):
-            email_type_plain = '_email/%s.txt' % template
-            email_type_html = '_email/%s.html' % template
-            return (
-                    select_template(('%s/%s' % (self._theme, email_type_plain[1:]), email_type_plain)),
-                    select_template(('%s/%s' % (self._theme, email_type_html[1:]), email_type_html)),
-                    )

+ 18 - 17
misago/apps/index.py

@@ -2,6 +2,7 @@ from datetime import timedelta
 from django.core.cache import cache
 from django.template import RequestContext
 from django.utils import timezone
+from misago.shortcuts import render_to_response
 from misago.models import Forum, Post, Rank, Session, Thread
 from misago.readstrackers import ForumsTracker
 
@@ -70,20 +71,20 @@ def index(request):
     Forum.objects.ignored_users(request.user, forums_list)
     
     # Render page
-    return request.theme.render_to_response('index.html',
-                                            {
-                                             'forums_list': forums_list,
-                                             'ranks_online': ranks_list,
-                                             'users_online': users_online,
-                                             'popular_threads': popular_threads,
-                                             'hook_above_forum_home': u'',
-                                             'hook_below_forum_home': u'',
-                                             'hook_above_home_forums_list': u'',
-                                             'hook_below_home_forums_list': u'',
-                                             'hook_above_home_sidepanel': u'',
-                                             'hook_after_home_sidepanel_ranks_online': u'',
-                                             'hook_after_home_sidepanel_popular_threads': u'',
-                                             'hook_after_home_sidepanel_forum_stats': u'',
-                                             'hook_below_home_sidepanel': u'',
-                                             },
-                                            context_instance=RequestContext(request));
+    return render_to_response('index.html',
+                              {
+                               'forums_list': forums_list,
+                               'ranks_online': ranks_list,
+                               'users_online': users_online,
+                               'popular_threads': popular_threads,
+                               'hook_above_forum_home': u'',
+                               'hook_below_forum_home': u'',
+                               'hook_above_home_forums_list': u'',
+                               'hook_below_home_forums_list': u'',
+                               'hook_above_home_sidepanel': u'',
+                               'hook_after_home_sidepanel_ranks_online': u'',
+                               'hook_after_home_sidepanel_popular_threads': u'',
+                               'hook_after_home_sidepanel_forum_stats': u'',
+                               'hook_below_home_sidepanel': u'',
+                               },
+                              context_instance=RequestContext(request));

+ 1 - 1
misago/middleware/theme.py

@@ -1,7 +1,7 @@
 from urlparse import urlparse
 from django.conf import settings
 from django.core.cache import cache
-from misago.template import activate_theme
+from misago.template.theme import activate_theme, active_theme
 
 class ThemeMiddleware(object):
     def process_request(self, request):

+ 15 - 1
misago/shortcuts.py

@@ -1 +1,15 @@
-from django.shortcuts import redirect
+from django.shortcuts import (redirect, render as django_render,
+                              render_to_response as django_render_to_response)
+from misago.template.middlewares import process_context
+from misago.template.theme import prefix_templates
+
+def render(request, template_name, dictionary=None, **kwargs):
+    dictionary = process_context(template_name, dictionary, kwargs.pop('context_instance', None))
+    template_name = prefix_templates(template_name, dictionary)
+    return django_render(request, template_name, dictionary, **kwargs)
+
+
+def render_to_response(template_name, dictionary=None, **kwargs):
+    dictionary = process_context(template_name, dictionary, kwargs.get('context_instance'))
+    template_name = prefix_templates(template_name, dictionary)
+    return django_render_to_response(template_name, dictionary, content_type=kwargs.get('content_type'))

+ 0 - 35
misago/template.py

@@ -1,35 +0,0 @@
-import threading
-from django.conf import settings
-from django.shortcuts import (render as django_render,
-                              render_to_response as django_render_to_response)
-from django.template import RequestContext
-from django.template.loader import render_to_string as django_render_to_string
-from django.utils.importlib import import_module
-
-_thread_local = threading.local()
-
-def activate_theme(theme):
-    if theme not in settings.INSTALLED_THEMES:
-        raise ValueError('"%s" is not correct theme name.' % theme)
-    if theme[0] == '_':
-        raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
-    _thread_local.misago_theme = theme;
-
-
-def theme_name():
-    try:
-        return _thread_local.misago_theme
-    except AttributeError:
-        return None
-
-
-def render(*args, **kwargs):
-    return django_render(*args, **kwargs)
-
-
-def render_to_string(*args, **kwargs):
-    return django_render_to_string(*args, **kwargs)
-
-
-def render_to_response(*args, **kwargs):
-    return django_render_to_response(*args, **kwargs)

+ 1 - 0
misago/template/__init__.py

@@ -0,0 +1 @@
+from django.template import RequestContext

+ 8 - 0
misago/template/loader.py

@@ -0,0 +1,8 @@
+from django.template.loader import render_to_string as django_render_to_string
+from misago.template.middleware import process_context
+from misago.template.theme import prefix_templates
+
+def render_to_string(template_name, dictionary=None, context_instance=None):
+    dictionary = process_context(template_name, dictionary, kwargs.get('context_instance'))
+    template_name = prefix_templates(template_name)
+    return django_render_to_string(template_name, dictionary)

+ 63 - 0
misago/template/middlewares.py

@@ -0,0 +1,63 @@
+from django.conf import settings
+from django.utils.importlib import import_module
+from misago.thread import local
+
+__all__ = ('merge_contexts', 'process_context', 'process_templates')
+
+def load_middlewares():
+    """
+    Populate _middlewares with list of template middlewares instances
+    """
+    middlewares = []
+    for extension in settings.TEMPLATE_MIDDLEWARES:
+        module = '.'.join(extension.split('.')[:-1])
+        extension = extension.split('.')[-1]
+        module = import_module(module)
+        middleware = getattr(module, extension)
+        middlewares += (middleware(), )
+    return tuple(middlewares)
+
+_middlewares = load_middlewares()
+
+def merge_contexts(dictionary=None, context_instance=None):
+    dictionary = dictionary or {}
+    if not context_instance:
+        return dictionary
+    context_instance.update(dictionary)
+    return context_instance
+
+
+_thread_local = local()
+
+
+def process_context(templates, dictionary=None, context_instance=None):
+    context = merge_contexts(dictionary, context_instance)
+    """
+    Put template context trough template middlewares
+    """
+    print _thread_local.__dict__.keys()
+    if _thread_local.misago_template_mutex:
+        return context
+    _thread_local.misago_template_mutex = True
+
+    for middleware in _middlewares:
+        try:
+            new_context = middleware.process_context(templates, context)
+            if new_context:
+                context = new_context
+        except AttributeError:
+            pass
+
+    _thread_local.misago_template_mutex = None
+    return context
+
+
+def process_templates(templates, context):
+    for middleware in _middlewares:
+        try:
+            new_templates = middleware.process_template(templates, context)
+            if new_templates:
+                return new_templates
+        except AttributeError:
+            pass
+    return templates

+ 38 - 0
misago/template/theme.py

@@ -0,0 +1,38 @@
+from django.conf import settings
+from misago.template.middlewares import process_templates
+from misago.thread import local
+
+__all__ = ('activate_theme', 'active_theme', 'prefix_templates')
+
+_thread_local = local()
+
+def activate_theme(theme):
+    """
+    Activate theme in current thread
+    """
+    if theme not in settings.INSTALLED_THEMES:
+        raise ValueError('"%s" is not correct theme name.' % theme)
+    if theme[0] == '_':
+        raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
+    print _thread_local.__dict__.keys()
+    _thread_local.misago_theme = theme;
+    _thread_local.misago_template_mutex = False
+
+
+def active_theme():
+    try:
+        return _thread_local.misago_theme
+    except AttributeError:
+        return None
+
+
+def prefix_templates(templates, dictionary=None):
+    templates = process_templates(templates, dictionary)
+    if isinstance(templates, str):
+        return ('%s/%s' % (_thread_local.misago_theme, templates), templates)
+    else:
+        prefixed = []
+        for template in templates:
+            prefixed.append('%s/%s' % (_thread_local.misago_theme, template))
+        prefixed += templates
+        return tuple(prefixed)

+ 6 - 0
misago/thread.py

@@ -0,0 +1,6 @@
+import threading
+
+_thread_local = threading.local()
+
+def local():
+    return _thread_local