From 45baccae858fa8bd9e9fdd4a555ff6c53455c195 Mon Sep 17 00:00:00 2001 From: Bridger Maxwell <bridgeyman@gmail.com> Date: Fri, 10 Aug 2012 11:31:29 -0400 Subject: [PATCH] Added a django template loader that can return Mako templates. Started pulling in new wiki. --- common/lib/mitxmako/mitxmako/makoloader.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/lib/mitxmako/mitxmako/template.py | 33 +++++++++++++++++++++++++++++++-- lms/envs/common.py | 24 +++++++++++++++++++++--- lms/templates/wiki/article.html | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ lms/urls.py | 15 +++++++++++---- requirements.txt | 1 + 6 files changed, 175 insertions(+), 9 deletions(-) create mode 100644 common/lib/mitxmako/mitxmako/makoloader.py create mode 100644 lms/templates/wiki/article.html diff --git a/common/lib/mitxmako/mitxmako/makoloader.py b/common/lib/mitxmako/mitxmako/makoloader.py new file mode 100644 index 0000000..fc1633c --- /dev/null +++ b/common/lib/mitxmako/mitxmako/makoloader.py @@ -0,0 +1,63 @@ + +from django.template.base import TemplateDoesNotExist +from django.template.loader import make_origin, get_template_from_string +from django.template.loaders.filesystem import Loader as FilesystemLoader +from django.template.loaders.app_directories import Loader as AppDirectoriesLoader + +from mitxmako.template import Template + +class MakoLoader(object): + """ + This is a Django loader object which will load the template as a + Mako template if the first line is "## mako". It is based off BaseLoader + in django.template.loader. + """ + + is_usable = False + + def __init__(self, base_loader): + # base_loader is an instance of a BaseLoader subclass + self.base_loader = base_loader + + def __call__(self, template_name, template_dirs=None): + return self.load_template(template_name, template_dirs) + + def load_template(self, template_name, template_dirs=None): + source, display_name = self.base_loader.load_template_source(template_name, template_dirs) + + if source.startswith("## mako\n"): + # This is a mako template + template = Template(text=source, uri=template_name) + return template, None + else: + # This is a regular template + origin = make_origin(display_name, self.load_template_source, template_name, template_dirs) + try: + template = get_template_from_string(source, origin, template_name) + return template, None + 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 source, display_name + + def load_template_source(self): + # Just having this makes the template load as an instance, instead of a class. + raise NotImplementedError + + def reset(self): + self.base_loader.reset() + + +class MakoFilesystemLoader(MakoLoader): + is_usable = True + + def __init__(self): + MakoLoader.__init__(self, FilesystemLoader()) + +class MakoAppDirectoriesLoader(MakoLoader): + is_usable = True + + def __init__(self): + MakoLoader.__init__(self, AppDirectoriesLoader()) diff --git a/common/lib/mitxmako/mitxmako/template.py b/common/lib/mitxmako/mitxmako/template.py index 911f5a5..e8fc24a 100644 --- a/common/lib/mitxmako/mitxmako/template.py +++ b/common/lib/mitxmako/mitxmako/template.py @@ -12,18 +12,47 @@ # See the License for the specific language governing permissions and # limitations under the License. +from django.conf import settings from mako.template import Template as MakoTemplate -from . import middleware +from mitxmako import middleware -django_variables = ['lookup', 'template_dirs', 'output_encoding', +django_variables = ['lookup', 'output_encoding', 'module_directory', 'encoding_errors'] class Template(MakoTemplate): + """ + This bridges the gap between a Mako template and a djano template. It can + be rendered like it is a django template because the arguments are transformed + in a way that MakoTemplate can understand. + """ + def __init__(self, *args, **kwargs): """Overrides base __init__ to provide django variable overrides""" if not kwargs.get('no_django', False): overrides = dict([(k, getattr(middleware, k, None),) for k in django_variables]) + overrides['lookup'] = overrides['lookup']['main'] kwargs.update(overrides) super(Template, self).__init__(*args, **kwargs) + + + def render(self, context_instance): + """ + This takes a render call with a context (from Django) and translates + it to a render call on the mako template. + """ + # collapse context_instance to a single dictionary for mako + context_dictionary = {} + + # In various testing contexts, there might not be a current request context. + if middleware.requestcontext is not None: + for d in middleware.requestcontext: + context_dictionary.update(d) + for d in context_instance: + context_dictionary.update(d) + context_dictionary['settings'] = settings + context_dictionary['MITX_ROOT_URL'] = settings.MITX_ROOT_URL + + return super(Template, self).render(**context_dictionary) + diff --git a/lms/envs/common.py b/lms/envs/common.py index 487e2ef..6354d58 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -111,6 +111,12 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'askbot.user_messages.context_processors.user_messages',#must be before auth 'django.contrib.auth.context_processors.auth', #this is required for admin 'django.core.context_processors.csrf', #necessary for csrf protection + + # Added for django-wiki + 'django.core.context_processors.media', + 'django.core.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + 'sekizai.context_processors.sekizai', ) @@ -281,9 +287,13 @@ STATICFILES_FINDERS = ( # List of callables that know how to import templates from various sources. TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'askbot.skins.loaders.filesystem_load_template_source', + 'mitxmako.makoloader.MakoFilesystemLoader', + 'mitxmako.makoloader.MakoAppDirectoriesLoader', + + # 'django.template.loaders.filesystem.Loader', + # 'django.template.loaders.app_directories.Loader', + + #'askbot.skins.loaders.filesystem_load_template_source', # 'django.template.loaders.eggs.Loader', ) @@ -514,6 +524,14 @@ INSTALLED_APPS = ( 'track', 'util', 'certificates', + + #For the wiki + 'wiki', # The new django-wiki from benjaoming + 'django_notify', + 'mptt', + 'sekizai', + 'wiki.plugins.attachments', + 'wiki.plugins.notifications', # For testing 'django_jasmine', diff --git a/lms/templates/wiki/article.html b/lms/templates/wiki/article.html new file mode 100644 index 0000000..45b3071 --- /dev/null +++ b/lms/templates/wiki/article.html @@ -0,0 +1,48 @@ +## mako +<%inherit file="../main.html"/> +<%namespace name='static' file='../static_content.html'/> + +<%block name="bodyextra"> + +This is a mako template with inheritance! + +</%block> + + +<!-- {% extends "wiki/base.html" %} +{% load wiki_tags i18n %} +{% load url from future %} + +{% block pagetitle %}{{ article.current_revision.title }}{% endblock %} + +{% block wiki_breadcrumbs %} +{% include "wiki/includes/breadcrumbs.html" %} +{% endblock %} + +{% block wiki_contents %} + <h1> Did it work? </h1> + <div class="tabbable tabs-top" style="margin-top: 20px;"> + <ul class="nav nav-tabs"> + <li style="float: left"> + <h1 style="margin-top: -10px;">{{ article.current_revision.title }}</h1> + </li> + {% with "view" as selected %} + {% include "wiki/includes/article_menu.html" %} + {% endwith %} + </ul> + <div class="tab-content"> + {% wiki_render article %} + </div> + </div> + + <div class="tabbable tabs-below" style="margin-top: 20px;"> + <ul class="nav nav-tabs"> + {% with "view" as selected %} + {% include "wiki/includes/article_menu.html" %} + {% endwith %} + <li style="margin-top: 10px;"><em>{% trans "Article last modified:" %} {{ article.current_revision.modified }}</em></li> + </ul> + </div> + +{% endblock %} --> + diff --git a/lms/urls.py b/lms/urls.py index bb3952b..44523dd 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -2,7 +2,6 @@ from django.conf import settings from django.conf.urls import patterns, include, url from django.contrib import admin from django.conf.urls.static import static - import django.contrib.auth.views # Uncomment the next two lines to enable the admin: @@ -144,9 +143,17 @@ if settings.COURSEWARE_ENABLED: # Multicourse wiki if settings.WIKI_ENABLED: - urlpatterns += ( - url(r'^wiki/', include('simplewiki.urls')), - url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/wiki/', include('simplewiki.urls')), + from wiki.urls import get_pattern as wiki_pattern + from django_notify.urls import get_pattern as notify_pattern + + # urlpatterns += ( + # url(r'^wiki/', include('simplewiki.urls')), + # url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/wiki/', include('simplewiki.urls')), + # ) + urlpatterns += ( + + url(r'wiki/', include(wiki_pattern())), + url(r'^notify/', include(notify_pattern())), ) if settings.QUICKEDIT: diff --git a/requirements.txt b/requirements.txt index ef16d2c..5905aa8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,4 +43,5 @@ django-robots django-ses django-storages django-threaded-multihost +-e git+git://github.com/benjaoming/django-wiki.git#egg=django-wiki -r repo-requirements.txt -- libgit2 0.26.0