Commit 9b89bd32 by Matjaz Gregoric

Make comprehensive theme work with django templates.

Comprehensive theming did not work with django templates (used by course wiki).

The reason it didn't work was that in order for the theme to work, theme template folder
has to be added to django template dirs setting *before* django startup.
After django startup, modifying `settings.DEFAULT_TEMPLATE_ENGINE['DIRS']` has no effect,
because at that point the template engine is already initialized with a copy of the
template dirs list.

Instead of running the theme startup code as an autostartup hook, we manually run it
*before* `django.setup()`. This is fine because theme startup code doesn't have to do
anything else besides modifying some settings and doesn't actually need django to be
initialized.
parent 8c26178d
......@@ -14,6 +14,8 @@ from monkey_patch import third_party_auth
import xmodule.x_module
import cms.lib.xblock.runtime
from openedx.core.djangoapps.theming.core import enable_comprehensive_theme
def run():
"""
......@@ -21,6 +23,11 @@ def run():
"""
third_party_auth.patch()
# Comprehensive theming needs to be set up before django startup,
# because modifying django template paths after startup has no effect.
if settings.COMPREHENSIVE_THEME_DIR:
enable_comprehensive_theme(settings.COMPREHENSIVE_THEME_DIR)
django.setup()
autostartup()
......
"""
Tests for wiki middleware.
"""
from django.conf import settings
from django.test.client import Client
from nose.plugins.attrib import attr
from wiki.models import URLPath
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from openedx.core.djangoapps.theming.test_util import with_comprehensive_theme
from courseware.tests.factories import InstructorFactory
from course_wiki.views import get_or_create_root
@attr('shard_1')
class TestComprehensiveTheming(ModuleStoreTestCase):
"""Tests for comprehensive theming of wiki pages."""
def setUp(self):
"""Test setup."""
super(TestComprehensiveTheming, self).setUp()
self.wiki = get_or_create_root()
self.course_math101 = CourseFactory.create(org='edx', number='math101', display_name='2014',
metadata={'use_unique_wiki_id': 'false'})
self.course_math101_instructor = InstructorFactory(course_key=self.course_math101.id, username='instructor',
password='secret')
self.wiki_math101 = URLPath.create_article(self.wiki, 'math101', title='math101')
self.client = Client()
self.client.login(username='instructor', password='secret')
@with_comprehensive_theme(settings.REPO_ROOT / 'themes/red-theme')
def test_themed_footer(self):
"""
Tests that theme footer is used rather than standard
footer when comprehensive theme is enabled.
"""
response = self.client.get('/courses/edx/math101/2014/wiki/math101/')
self.assertEqual(response.status_code, 200)
# This string comes from themes/red-theme/lms/templates/footer.html
self.assertContains(response, "super-ugly")
......@@ -18,6 +18,7 @@ from monkey_patch import third_party_auth
import xmodule.x_module
import lms_xblock.runtime
from openedx.core.djangoapps.theming.core import enable_comprehensive_theme
from microsite_configuration import microsite
log = logging.getLogger(__name__)
......@@ -33,6 +34,11 @@ def run():
if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH', False):
enable_third_party_auth()
# Comprehensive theming needs to be set up before django startup,
# because modifying django template paths after startup has no effect.
if settings.COMPREHENSIVE_THEME_DIR:
enable_comprehensive_theme(settings.COMPREHENSIVE_THEME_DIR)
# We currently use 2 template rendering engines, mako and django_templates,
# and one of them (django templates), requires the directories be added
# before the django.setup().
......
......@@ -5,8 +5,6 @@ from path import Path
from django.conf import settings
import edxmako
def comprehensive_theme_changes(theme_dir):
"""
......@@ -20,14 +18,14 @@ def comprehensive_theme_changes(theme_dir):
* 'settings': a dictionary of settings names and their new values.
* 'mako_paths': a list of directories to prepend to the edxmako
template lookup path.
* 'template_paths': a list of directories to prepend to template
lookup path.
"""
changes = {
'settings': {},
'mako_paths': [],
'template_paths': [],
}
root = Path(settings.PROJECT_ROOT)
if root.name == "":
......@@ -37,8 +35,7 @@ def comprehensive_theme_changes(theme_dir):
templates_dir = component_dir / "templates"
if templates_dir.isdir():
changes['settings']['TEMPLATE_DIRS'] = [templates_dir] + settings.DEFAULT_TEMPLATE_ENGINE['DIRS']
changes['mako_paths'].append(templates_dir)
changes['template_paths'].append(templates_dir)
staticfiles_dir = component_dir / "static"
if staticfiles_dir.isdir():
......@@ -64,5 +61,6 @@ def enable_comprehensive_theme(theme_dir):
# Use the changes
for name, value in changes['settings'].iteritems():
setattr(settings, name, value)
for template_dir in changes['mako_paths']:
edxmako.paths.add_lookup('main', template_dir, prepend=True)
for template_dir in changes['template_paths']:
settings.DEFAULT_TEMPLATE_ENGINE['DIRS'].insert(0, template_dir)
settings.MAKO_TEMPLATES['main'].insert(0, template_dir)
"""
Startup code for Comprehensive Theming
"""
from path import Path as path
from django.conf import settings
from .core import enable_comprehensive_theme
def run():
"""Enable comprehensive theming, if we should."""
if settings.COMPREHENSIVE_THEME_DIR:
enable_comprehensive_theme(theme_dir=path(settings.COMPREHENSIVE_THEME_DIR))
......@@ -9,6 +9,7 @@ import os.path
from mock import patch
from django.conf import settings
from django.template import Engine
from django.test.utils import override_settings
import edxmako
......@@ -35,11 +36,14 @@ def with_comprehensive_theme(theme_dir):
@wraps(func)
def _decorated(*args, **kwargs): # pylint: disable=missing-docstring
with override_settings(COMPREHENSIVE_THEME_DIR=theme_dir, **changes['settings']):
default_engine = Engine.get_default()
dirs = default_engine.dirs[:]
with edxmako.save_lookups():
for template_dir in changes['mako_paths']:
for template_dir in changes['template_paths']:
edxmako.paths.add_lookup('main', template_dir, prepend=True)
return func(*args, **kwargs)
dirs.insert(0, template_dir)
with patch.object(default_engine, 'dirs', dirs):
return func(*args, **kwargs)
return _decorated
return _decorator
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment