Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fdc50c3a
Commit
fdc50c3a
authored
Nov 29, 2017
by
Jeremy Bowman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PLAT-1419 Make edxmako a proper template backend
parent
989c3a30
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
308 additions
and
239 deletions
+308
-239
cms/djangoapps/contentstore/views/helpers.py
+3
-3
cms/envs/common.py
+41
-20
common/djangoapps/edxmako/__init__.py
+10
-0
common/djangoapps/edxmako/apps.py
+5
-2
common/djangoapps/edxmako/backend.py
+67
-0
common/djangoapps/edxmako/makoloader.py
+5
-4
common/djangoapps/edxmako/management/__init__.py
+0
-0
common/djangoapps/edxmako/management/commands/__init__.py
+0
-0
common/djangoapps/edxmako/request_context.py
+0
-19
common/djangoapps/edxmako/shortcuts.py
+14
-43
common/djangoapps/edxmako/template.py
+65
-23
common/djangoapps/edxmako/templatetag_helpers.py
+0
-52
common/lib/capa/capa/checker.py
+5
-8
lms/djangoapps/static_template_view/views.py
+3
-3
lms/envs/common.py
+62
-45
lms/envs/test.py
+1
-1
openedx/core/djangoapps/credit/email_utils.py
+1
-1
openedx/core/djangoapps/debug/views.py
+2
-2
openedx/core/lib/derived.py
+16
-11
openedx/core/lib/tests/test_derived.py
+8
-2
No files found.
cms/djangoapps/contentstore/views/helpers.py
View file @
fdc50c3a
...
...
@@ -44,11 +44,11 @@ def event(request):
return
HttpResponse
(
status
=
204
)
def
render_from_lms
(
template_name
,
dictionary
,
context
=
None
,
namespace
=
'main'
):
def
render_from_lms
(
template_name
,
dictionary
,
namespace
=
'main'
):
"""
Render a template using the LMS M
AKO_TEMPLATES
Render a template using the LMS M
ako templates
"""
return
render_to_string
(
template_name
,
dictionary
,
context
,
namespace
=
"lms."
+
namespace
)
return
render_to_string
(
template_name
,
dictionary
,
namespace
=
"lms."
+
namespace
)
def
get_parent_xblock
(
xblock
):
...
...
cms/envs/common.py
View file @
fdc50c3a
...
...
@@ -119,7 +119,7 @@ from lms.envs.common import (
VIDEO_TRANSCRIPTS_SETTINGS
,
# Methods to derive settings
_make_ma
in_mako_template
s
,
_make_ma
ko_template_dir
s
,
_make_locale_paths
,
)
from
path
import
Path
as
path
...
...
@@ -134,7 +134,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
get_theme_base_dirs_from_settings
)
from
openedx.core.lib.license
import
LicenseMixin
from
openedx.core.lib.derived
import
derived
,
derived_
dict
_entry
from
openedx.core.lib.derived
import
derived
,
derived_
collection
_entry
from
openedx.core.release
import
doc_version
############################ FEATURE CONFIGURATION #############################
...
...
@@ -310,11 +310,9 @@ GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
############################# TEMPLATE CONFIGURATION #############################
# Mako templating
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
import
tempfile
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_cms'
)
MAKO_TEMPLATES
=
{}
MAIN_MAKO_TEMPLATES_BASE
=
[
MAKO_TEMPLATE_DIRS_BASE
=
[
PROJECT_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'djangoapps'
/
'pipeline_mako'
/
'templates'
,
...
...
@@ -324,19 +322,27 @@ MAIN_MAKO_TEMPLATES_BASE = [
OPENEDX_ROOT
/
'core'
/
'lib'
/
'license'
/
'templates'
,
CMS_ROOT
/
'djangoapps'
/
'pipeline_js'
/
'templates'
,
]
MAKO_TEMPLATES
[
'lms.main'
]
=
lms
.
envs
.
common
.
MAIN_MAKO_TEMPLATES_BASE
MAKO_TEMPLATES
[
'main'
]
=
_make_main_mako_templates
derived_dict_entry
(
'MAKO_TEMPLATES'
,
'main'
)
CONTEXT_PROCESSORS
=
(
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
'dealer.contrib.django.staff.context_processor'
,
# access git revision
'help_tokens.context_processor'
,
)
# Django templating
TEMPLATES
=
[
{
'NAME'
:
'django'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
# Instead, look for template source files in these dirs.
'DIRS'
:
MAIN_MAKO_TEMPLATES_BASE
,
'DIRS'
:
_make_mako_template_dirs
,
# Options specific to this backend.
'OPTIONS'
:
{
'loaders'
:
(
...
...
@@ -346,21 +352,36 @@ TEMPLATES = [
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
),
'context_processors'
:
(
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
'dealer.contrib.django.staff.context_processor'
,
# access git revision
'help_tokens.context_processor'
,
),
'context_processors'
:
CONTEXT_PROCESSORS
,
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
}
}
},
{
'NAME'
:
'mako'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
'APP_DIRS'
:
False
,
'DIRS'
:
_make_mako_template_dirs
,
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
'debug'
:
False
,
}
},
{
# This separate copy of the Mako backend is used to render previews using the LMS templates
'NAME'
:
'preview'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
'APP_DIRS'
:
False
,
'DIRS'
:
lms
.
envs
.
common
.
MAKO_TEMPLATE_DIRS_BASE
,
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
'debug'
:
False
,
'namespace'
:
'lms.main'
,
}
},
]
derived_collection_entry
(
'TEMPLATES'
,
0
,
'DIRS'
)
derived_collection_entry
(
'TEMPLATES'
,
1
,
'DIRS'
)
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
##############################################################################
...
...
common/djangoapps/edxmako/__init__.py
View file @
fdc50c3a
...
...
@@ -14,3 +14,13 @@
LOOKUP
=
{}
from
.paths
import
add_lookup
,
lookup_template
,
clear_lookups
,
save_lookups
class
Engines
(
object
):
"""
Aliases for the available template engines.
Note that the preview engine is only configured for cms.
"""
DJANGO
=
'django'
MAKO
=
'mako'
PREVIEW
=
'preview'
common/djangoapps/edxmako/apps.py
View file @
fdc50c3a
...
...
@@ -20,8 +20,11 @@ class EdxMakoConfig(AppConfig):
IMPORTANT: This method can be called multiple times during application startup. Any changes to this method
must be safe for multiple callers during startup phase.
"""
template_locations
=
settings
.
MAKO_TEMPLATES
for
namespace
,
directories
in
template_locations
.
items
():
for
backend
in
settings
.
TEMPLATES
:
if
'edxmako'
not
in
backend
[
'BACKEND'
]:
continue
namespace
=
backend
[
'OPTIONS'
]
.
get
(
'namespace'
,
'main'
)
directories
=
backend
[
'DIRS'
]
clear_lookups
(
namespace
)
for
directory
in
directories
:
add_lookup
(
namespace
,
directory
)
common/djangoapps/edxmako/backend.py
0 → 100644
View file @
fdc50c3a
"""
Django template system engine for Mako templates.
"""
from
__future__
import
absolute_import
,
unicode_literals
import
logging
from
django.template
import
TemplateDoesNotExist
,
TemplateSyntaxError
from
django.template.backends.base
import
BaseEngine
from
django.template.context
import
_builtin_context_processors
from
django.utils.functional
import
cached_property
from
django.utils.module_loading
import
import_string
from
mako.exceptions
import
MakoException
,
TopLevelLookupException
,
text_error_template
from
openedx.core.djangoapps.theming.helpers
import
get_template_path
from
.paths
import
lookup_template
from
.template
import
Template
LOGGER
=
logging
.
getLogger
(
__name__
)
class
Mako
(
BaseEngine
):
"""
A Mako template engine to be added to the ``TEMPLATES`` Django setting.
"""
app_dirname
=
'templates'
def
__init__
(
self
,
params
):
"""
Fetches template options, initializing BaseEngine properties,
and assigning our Mako default settings.
Note that OPTIONS contains backend-specific settings.
:param params: This is simply the template dict you
define in your settings file.
"""
params
=
params
.
copy
()
options
=
params
.
pop
(
'OPTIONS'
)
.
copy
()
super
(
Mako
,
self
)
.
__init__
(
params
)
self
.
context_processors
=
options
.
pop
(
'context_processors'
,
[])
self
.
namespace
=
options
.
pop
(
'namespace'
,
'main'
)
def
from_string
(
self
,
template_code
):
try
:
return
Template
(
template_code
)
except
MakoException
:
message
=
text_error_template
()
.
render
()
raise
TemplateSyntaxError
(
message
)
def
get_template
(
self
,
template_name
):
"""
Loads and returns a template for the given name.
"""
template_name
=
get_template_path
(
template_name
)
try
:
return
Template
(
lookup_template
(
self
.
namespace
,
template_name
),
engine
=
self
)
except
TopLevelLookupException
:
raise
TemplateDoesNotExist
(
template_name
)
@cached_property
def
template_context_processors
(
self
):
"""
Collect and cache the active context processors.
"""
context_processors
=
_builtin_context_processors
context_processors
+=
tuple
(
self
.
context_processors
)
return
tuple
(
import_string
(
path
)
for
path
in
context_processors
)
common/djangoapps/edxmako/makoloader.py
View file @
fdc50c3a
...
...
@@ -2,7 +2,7 @@ import logging
from
django.conf
import
settings
from
django.core.exceptions
import
ImproperlyConfigured
from
django.template
import
Engine
from
django.template
import
Engine
,
engines
from
django.template.base
import
TemplateDoesNotExist
from
django.template.loaders.app_directories
import
Loader
as
AppDirectoriesLoader
from
django.template.loaders.filesystem
import
Loader
as
FilesystemLoader
...
...
@@ -16,8 +16,8 @@ log = logging.getLogger(__name__)
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
Base
Loader
in django.template.loader.
Mako template if the first line is "## mako". It is based off Loader
in django.template.loader
s.base
.
We need this in order to be able to include mako templates inside main_django.html.
"""
...
...
@@ -53,7 +53,8 @@ class MakoLoader(object):
output_encoding
=
'utf-8'
,
default_filters
=
[
'decode.utf8'
],
encoding_errors
=
'replace'
,
uri
=
template_name
)
uri
=
template_name
,
engine
=
engines
[
'mako'
])
return
template
,
None
else
:
# This is a regular template
...
...
common/djangoapps/edxmako/management/__init__.py
deleted
100644 → 0
View file @
989c3a30
common/djangoapps/edxmako/management/commands/__init__.py
deleted
100644 → 0
View file @
989c3a30
common/djangoapps/edxmako/request_context.py
View file @
fdc50c3a
...
...
@@ -20,24 +20,12 @@ Methods for creating RequestContext for using with Mako templates.
from
crum
import
get_current_request
from
django.conf
import
settings
from
django.template
import
RequestContext
from
django.template.context
import
_builtin_context_processors
from
django.utils.module_loading
import
import_string
import
request_cache
from
util.request
import
safe_get_host
def
get_template_context_processors
():
"""
Returns the context processors defined in settings.TEMPLATES.
"""
context_processors
=
_builtin_context_processors
context_processors
+=
tuple
(
settings
.
DEFAULT_TEMPLATE_ENGINE
[
'OPTIONS'
][
'context_processors'
])
return
tuple
(
import_string
(
path
)
for
path
in
context_processors
)
def
get_template_request_context
(
request
=
None
):
"""
Returns the template processing context to use for the current request,
...
...
@@ -60,13 +48,6 @@ def get_template_request_context(request=None):
context
[
'is_secure'
]
=
request
.
is_secure
()
context
[
'site'
]
=
safe_get_host
(
request
)
# This used to happen when a RequestContext object was initialized but was
# moved to a different part of the logic when template engines were introduced.
# Since we are not using template engines we do this here.
# https://github.com/django/django/commit/37505b6397058bcc3460f23d48a7de9641cd6ef0
for
processor
in
get_template_context_processors
():
context
.
update
(
processor
(
request
))
request_cache_dict
[
cache_key
]
=
context
return
context
common/djangoapps/edxmako/shortcuts.py
View file @
fdc50c3a
...
...
@@ -18,12 +18,12 @@ from urlparse import urljoin
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.http
import
HttpResponse
from
django.template
import
Context
from
django.template
import
engines
from
edxmako
import
lookup_template
from
edxmako.request_context
import
get_template_request_context
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.theming.helpers
import
get_template_path
,
is_request_in_themed_site
from
openedx.core.djangoapps.theming.helpers
import
is_request_in_themed_site
from
.
import
Engines
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -131,7 +131,7 @@ def footer_context_processor(request): # pylint: disable=unused-argument
)
def
render_to_string
(
template_name
,
dictionary
,
context
=
None
,
namespace
=
'main'
,
request
=
None
):
def
render_to_string
(
template_name
,
dictionary
,
namespace
=
'main'
,
request
=
None
):
"""
Render a Mako template to as a string.
...
...
@@ -147,52 +147,23 @@ def render_to_string(template_name, dictionary, context=None, namespace='main',
from the template paths specified in configuration.
dictionary: A dictionary of variables to insert into the template during
rendering.
context: A :class:`~django.template.Context` with values to make
available to the template.
namespace: The Mako namespace to find the named template in.
request: The request to use to construct the RequestContext for rendering
this template. If not supplied, the current request will be used.
"""
if
namespace
==
'lms.main'
:
engine
=
engines
[
Engines
.
PREVIEW
]
else
:
engine
=
engines
[
Engines
.
MAKO
]
template
=
engine
.
get_template
(
template_name
)
return
template
.
render
(
dictionary
,
request
)
template_name
=
get_template_path
(
template_name
)
context_instance
=
Context
(
dictionary
)
# add dictionary to context_instance
context_instance
.
update
(
dictionary
or
{})
# collapse context_instance to a single dictionary for mako
context_dictionary
=
{}
context_instance
[
'settings'
]
=
settings
context_instance
[
'EDX_ROOT_URL'
]
=
settings
.
EDX_ROOT_URL
context_instance
[
'marketing_link'
]
=
marketing_link
context_instance
[
'is_any_marketing_link_set'
]
=
is_any_marketing_link_set
context_instance
[
'is_marketing_link_set'
]
=
is_marketing_link_set
# In various testing contexts, there might not be a current request context.
request_context
=
get_template_request_context
(
request
)
if
request_context
:
for
item
in
request_context
:
context_dictionary
.
update
(
item
)
for
item
in
context_instance
:
context_dictionary
.
update
(
item
)
if
context
:
context_dictionary
.
update
(
context
)
# "Fix" CSRF token by evaluating the lazy object
KEY_CSRF_TOKENS
=
(
'csrf_token'
,
'csrf'
)
for
key
in
KEY_CSRF_TOKENS
:
if
key
in
context_dictionary
:
context_dictionary
[
key
]
=
unicode
(
context_dictionary
[
key
])
# fetch and render template
template
=
lookup_template
(
namespace
,
template_name
)
return
template
.
render_unicode
(
**
context_dictionary
)
def
render_to_response
(
template_name
,
dictionary
=
None
,
context_instance
=
None
,
namespace
=
'main'
,
request
=
None
,
**
kwargs
):
def
render_to_response
(
template_name
,
dictionary
=
None
,
namespace
=
'main'
,
request
=
None
,
**
kwargs
):
"""
Returns a HttpResponse whose content is filled with the result of calling
lookup.get_template(args[0]).render with the passed arguments.
"""
dictionary
=
dictionary
or
{}
return
HttpResponse
(
render_to_string
(
template_name
,
dictionary
,
context_instance
,
namespace
,
request
),
**
kwargs
)
return
HttpResponse
(
render_to_string
(
template_name
,
dictionary
,
namespace
,
request
),
**
kwargs
)
common/djangoapps/edxmako/template.py
View file @
fdc50c3a
...
...
@@ -13,47 +13,89 @@
# limitations under the License.
from
django.conf
import
settings
from
django.template
import
Context
,
engines
from
mako.template
import
Template
as
MakoTemplate
from
six
import
text_type
import
edxmako
from
edxmako
.request_context
import
get_template_request_context
from
edxmako.shortcuts
import
marketing_link
from
.
import
Engines
,
LOOKUP
from
.request_context
import
get_template_request_context
from
.shortcuts
import
is_any_marketing_link_set
,
is_marketing_link_set
,
marketing_link
KEY_CSRF_TOKENS
=
(
'csrf_token'
,
'csrf'
)
# TODO: We should make this a Django Template subclass that simply has the MakoTemplate inside of it? (Intead of inheriting from MakoTemplate)
class
Template
(
MakoTemplate
):
class
Template
(
object
):
"""
This bridges the gap between a Mako template and a
djan
o template. It can
be rendered like it is a
d
jango template because the arguments are transformed
This bridges the gap between a Mako template and a
Djang
o template. It can
be rendered like it is a
D
jango 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
):
kwargs
[
'lookup'
]
=
edxmako
.
LOOKUP
[
'main'
]
super
(
Template
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
engine
=
kwargs
.
pop
(
'engine'
,
engines
[
Engines
.
MAKO
])
if
len
(
args
)
and
isinstance
(
args
[
0
],
MakoTemplate
):
self
.
mako_template
=
args
[
0
]
else
:
kwargs
[
'lookup'
]
=
LOOKUP
[
'main'
]
self
.
mako_template
=
MakoTemplate
(
*
args
,
**
kwargs
)
def
render
(
self
,
context
_instanc
e
):
def
render
(
self
,
context
=
None
,
request
=
Non
e
):
"""
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
=
{}
context_object
=
self
.
_get_context_object
(
request
)
context_dictionary
=
self
.
_get_context_processors_output_dict
(
context_object
)
if
isinstance
(
context
,
Context
):
context_dictionary
.
update
(
context
.
flatten
())
elif
context
is
not
None
:
context_dictionary
.
update
(
context
)
self
.
_add_core_context
(
context_dictionary
)
self
.
_evaluate_lazy_csrf_tokens
(
context_dictionary
)
return
self
.
mako_template
.
render_unicode
(
**
context_dictionary
)
@staticmethod
def
_get_context_object
(
request
):
"""
Get a Django RequestContext or Context, as appropriate for the situation.
In some tests, there might not be a current request.
"""
request_context
=
get_template_request_context
(
request
)
if
request_context
is
not
None
:
return
request_context
else
:
return
Context
({})
# In various testing contexts, there might not be a current request context.
request_context
=
get_template_request_context
()
if
request_context
:
for
item
in
request_context
:
context_dictionary
.
update
(
item
)
for
item
in
context_instance
:
context_dictionary
.
update
(
item
)
def
_get_context_processors_output_dict
(
self
,
context_object
):
"""
Run the context processors for the given context and get the output as a new dictionary.
"""
with
context_object
.
bind_template
(
self
):
return
context_object
.
flatten
()
@staticmethod
def
_add_core_context
(
context_dictionary
):
"""
Add to the given dictionary context variables which should always be
present, even when context processors aren't run during tests. Using
a context processor should almost always be preferred to adding more
variables here.
"""
context_dictionary
[
'settings'
]
=
settings
context_dictionary
[
'EDX_ROOT_URL'
]
=
settings
.
EDX_ROOT_URL
context_dictionary
[
'django_context'
]
=
context_instance
context_dictionary
[
'marketing_link'
]
=
marketing_link
context_dictionary
[
'is_any_marketing_link_set'
]
=
is_any_marketing_link_set
context_dictionary
[
'is_marketing_link_set'
]
=
is_marketing_link_set
return
super
(
Template
,
self
)
.
render_unicode
(
**
context_dictionary
)
@staticmethod
def
_evaluate_lazy_csrf_tokens
(
context_dictionary
):
"""
Evaluate any lazily-evaluated CSRF tokens in the given context.
"""
for
key
in
KEY_CSRF_TOKENS
:
if
key
in
context_dictionary
:
context_dictionary
[
key
]
=
text_type
(
context_dictionary
[
key
])
common/djangoapps/edxmako/templatetag_helpers.py
deleted
100644 → 0
View file @
989c3a30
from
django.template
import
loader
from
django.template.base
import
Context
,
Template
from
django.template.loader
import
get_template
,
select_template
def
django_template_include
(
file_name
,
mako_context
):
"""
This can be used within a mako template to include a django template
in the way that a django-style {
%
include
%
} does. Pass it context
which can be the mako context ('context') or a dictionary.
"""
dictionary
=
dict
(
mako_context
)
return
loader
.
render_to_string
(
file_name
,
dictionary
=
dictionary
)
def
render_inclusion
(
func
,
file_name
,
takes_context
,
django_context
,
*
args
,
**
kwargs
):
"""
This allows a mako template to call a template tag function (written
for django templates) that is an "inclusion tag". These functions are
decorated with @register.inclusion_tag.
-func: This is the function that is registered as an inclusion tag.
You must import it directly using a python import statement.
-file_name: This is the filename of the template, passed into the
@register.inclusion_tag statement.
-takes_context: This is a parameter of the @register.inclusion_tag.
-django_context: This is an instance of the django context. If this
is a mako template rendered through the regular django rendering calls,
a copy of the django context is available as 'django_context'.
-*args and **kwargs are the arguments to func.
"""
if
takes_context
:
args
=
[
django_context
]
+
list
(
args
)
_dict
=
func
(
*
args
,
**
kwargs
)
if
isinstance
(
file_name
,
Template
):
t
=
file_name
elif
not
isinstance
(
file_name
,
basestring
)
and
is_iterable
(
file_name
):
t
=
select_template
(
file_name
)
else
:
t
=
get_template
(
file_name
)
nodelist
=
t
.
nodelist
new_context
=
Context
(
_dict
)
csrf_token
=
django_context
.
get
(
'csrf_token'
,
None
)
if
csrf_token
is
not
None
:
new_context
[
'csrf_token'
]
=
csrf_token
return
nodelist
.
render
(
new_context
)
common/lib/capa/capa/checker.py
View file @
fdc50c3a
...
...
@@ -24,14 +24,11 @@ class DemoSystem(object):
self
.
lookup
=
TemplateLookup
(
directories
=
[
path
(
__file__
)
.
dirname
()
/
'templates'
])
self
.
DEBUG
=
True
def
render_template
(
self
,
template_filename
,
dictionary
,
context
=
None
):
if
context
is
None
:
context
=
{}
context_dict
=
{}
context_dict
.
update
(
dictionary
)
context_dict
.
update
(
context
)
return
self
.
lookup
.
get_template
(
template_filename
)
.
render
(
**
context_dict
)
def
render_template
(
self
,
template_filename
,
dictionary
):
"""
Render the specified template with the given dictionary of context data.
"""
return
self
.
lookup
.
get_template
(
template_filename
)
.
render
(
**
dictionary
)
def
main
():
...
...
lms/djangoapps/static_template_view/views.py
View file @
fdc50c3a
...
...
@@ -8,8 +8,8 @@ import mimetypes
from
django.conf
import
settings
from
django.http
import
Http404
,
HttpResponseNotFound
,
HttpResponseServerError
from
django.shortcuts
import
redirect
from
django.template
import
TemplateDoesNotExist
from
django.views.decorators.csrf
import
ensure_csrf_cookie
from
mako.exceptions
import
TopLevelLookupException
from
edxmako.shortcuts
import
render_to_response
,
render_to_string
from
util.cache
import
cache_if_anonymous
...
...
@@ -51,7 +51,7 @@ def render(request, template):
if
template
==
'honor.html'
:
context
[
'allow_iframing'
]
=
True
return
render_to_response
(
'static_templates/'
+
template
,
context
,
content_type
=
content_type
)
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
raise
Http404
...
...
@@ -68,7 +68,7 @@ def render_press_release(request, slug):
template
=
slug
.
lower
()
.
replace
(
'-'
,
'_'
)
+
".html"
try
:
resp
=
render_to_response
(
'static_templates/press_releases/'
+
template
,
{})
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
raise
Http404
else
:
return
resp
...
...
lms/envs/common.py
View file @
fdc50c3a
...
...
@@ -43,7 +43,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
get_themes_unchecked
,
get_theme_base_dirs_from_settings
)
from
openedx.core.lib.derived
import
derived
,
derived_
dict
_entry
from
openedx.core.lib.derived
import
derived
,
derived_
collection
_entry
from
openedx.core.release
import
doc_version
from
xmodule.modulestore.modulestore_settings
import
update_module_store_settings
from
xmodule.modulestore.edit_info
import
EditInfoMixin
...
...
@@ -535,11 +535,9 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
################################## TEMPLATE CONFIGURATION #####################################
# Mako templating
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
import
tempfile
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_lms'
)
MAKO_TEMPLATES
=
{}
MAIN_MAKO_TEMPLATES_BASE
=
[
MAKO_TEMPLATE_DIRS_BASE
=
[
PROJECT_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'lib'
/
'capa'
/
'capa'
/
'templates'
,
...
...
@@ -550,24 +548,55 @@ MAIN_MAKO_TEMPLATES_BASE = [
]
def
_make_ma
in_mako_template
s
(
settings
):
def
_make_ma
ko_template_dir
s
(
settings
):
"""
Derives the final M
AKO_TEMPLATES['main'] setting
from other settings.
Derives the final M
ako template directories list
from other settings.
"""
if
settings
.
ENABLE_COMPREHENSIVE_THEMING
:
themes_dirs
=
get_theme_base_dirs_from_settings
(
settings
.
COMPREHENSIVE_THEME_DIRS
)
for
theme
in
get_themes_unchecked
(
themes_dirs
,
PROJECT_ROOT
):
if
theme
.
themes_base_dir
not
in
settings
.
MA
IN_MAKO_TEMPLATE
S_BASE
:
settings
.
MA
IN_MAKO_TEMPLATE
S_BASE
.
insert
(
0
,
theme
.
themes_base_dir
)
for
theme
in
get_themes_unchecked
(
themes_dirs
,
settings
.
PROJECT_ROOT
):
if
theme
.
themes_base_dir
not
in
settings
.
MA
KO_TEMPLATE_DIR
S_BASE
:
settings
.
MA
KO_TEMPLATE_DIR
S_BASE
.
insert
(
0
,
theme
.
themes_base_dir
)
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
settings
.
MAIN_MAKO_TEMPLATES_BASE
.
insert
(
0
,
settings
.
MICROSITE_ROOT_DIR
)
return
settings
.
MAIN_MAKO_TEMPLATES_BASE
MAKO_TEMPLATES
[
'main'
]
=
_make_main_mako_templates
derived_dict_entry
(
'MAKO_TEMPLATES'
,
'main'
)
settings
.
MAKO_TEMPLATE_DIRS_BASE
.
insert
(
0
,
settings
.
MICROSITE_ROOT_DIR
)
return
settings
.
MAKO_TEMPLATE_DIRS_BASE
CONTEXT_PROCESSORS
=
[
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
# Added for django-wiki
'django.template.context_processors.media'
,
'django.template.context_processors.tz'
,
'django.contrib.messages.context_processors.messages'
,
'sekizai.context_processors.sekizai'
,
# Hack to get required link URLs to password reset templates
'edxmako.shortcuts.marketing_link_context_processor'
,
# Shoppingcart processor (detects if request.user has a cart)
'shoppingcart.context_processor.user_has_cart_context_processor'
,
# Timezone processor (sends language and time_zone preference)
'courseware.context_processor.user_timezone_locale_prefs'
,
# Allows the open edX footer to be leveraged in Django Templates.
'edxmako.shortcuts.footer_context_processor'
,
# Online contextual help
'help_tokens.context_processor'
,
'openedx.core.djangoapps.site_configuration.context_processors.configuration_context'
]
# Django templating
TEMPLATES
=
[
{
'NAME'
:
'django'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
...
...
@@ -588,41 +617,27 @@ TEMPLATES = [
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
],
'context_processors'
:
[
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
# Added for django-wiki
'django.template.context_processors.media'
,
'django.template.context_processors.tz'
,
'django.contrib.messages.context_processors.messages'
,
'sekizai.context_processors.sekizai'
,
# Hack to get required link URLs to password reset templates
'edxmako.shortcuts.marketing_link_context_processor'
,
# Shoppingcart processor (detects if request.user has a cart)
'shoppingcart.context_processor.user_has_cart_context_processor'
,
# Timezone processor (sends language and time_zone preference)
'courseware.context_processor.user_timezone_locale_prefs'
,
# Allows the open edX footer to be leveraged in Django Templates.
'edxmako.shortcuts.footer_context_processor'
,
# Online contextual help
'help_tokens.context_processor'
,
'openedx.core.djangoapps.site_configuration.context_processors.configuration_context'
],
'context_processors'
:
CONTEXT_PROCESSORS
,
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
}
}
},
{
'NAME'
:
'mako'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
# Instead, look for template source files in these dirs.
'DIRS'
:
_make_mako_template_dirs
,
# Options specific to this backend.
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
,
}
},
]
derived_collection_entry
(
'TEMPLATES'
,
1
,
'DIRS'
)
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
DEFAULT_TEMPLATE_ENGINE_DIRS
=
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
][:]
...
...
@@ -634,8 +649,10 @@ def _add_microsite_dirs_to_default_template_engine(settings):
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
DEFAULT_TEMPLATE_ENGINE_DIRS
.
append
(
settings
.
MICROSITE_ROOT_DIR
)
return
DEFAULT_TEMPLATE_ENGINE_DIRS
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
]
=
_add_microsite_dirs_to_default_template_engine
derived_
dict
_entry
(
'DEFAULT_TEMPLATE_ENGINE'
,
'DIRS'
)
derived_
collection
_entry
(
'DEFAULT_TEMPLATE_ENGINE'
,
'DIRS'
)
###############################################################################################
...
...
lms/envs/test.py
View file @
fdc50c3a
...
...
@@ -491,7 +491,7 @@ MICROSITE_LOGISTRATION_HOSTNAME = 'logistration.testserver'
TEST_THEME
=
COMMON_ROOT
/
"test"
/
"test-theme"
# add extra template directory for test-only templates
MA
IN_MAKO_TEMPLATE
S_BASE
.
extend
([
MA
KO_TEMPLATE_DIR
S_BASE
.
extend
([
COMMON_ROOT
/
'test'
/
'templates'
,
COMMON_ROOT
/
'test'
/
'test_sites'
,
REPO_ROOT
/
'openedx'
/
'core'
/
'djangolib'
/
'tests'
/
'templates'
,
...
...
openedx/core/djangoapps/credit/email_utils.py
View file @
fdc50c3a
...
...
@@ -113,7 +113,7 @@ def send_credit_notifications(username, course_key):
else
:
email_body_content
=
''
email_body
=
Template
(
email_body_content
)
.
render
(
[
context
]
)
email_body
=
Template
(
email_body_content
)
.
render
(
context
)
msg_alternative
.
attach
(
SafeMIMEText
(
email_body
,
_subtype
=
'html'
,
_charset
=
'utf-8'
))
# attach logo image
...
...
openedx/core/djangoapps/debug/views.py
View file @
fdc50c3a
...
...
@@ -4,9 +4,9 @@ These views will NOT be shown on production: trying to access them will result
in a 404 error.
"""
from
django.http
import
HttpResponseNotFound
from
django.template
import
TemplateDoesNotExist
from
django.utils.translation
import
ugettext
as
_
from
edxmako.shortcuts
import
render_to_response
from
mako.exceptions
import
TopLevelLookupException
from
openedx.core.djangoapps.util.user_messages
import
PageLevelMessages
...
...
@@ -51,5 +51,5 @@ def show_reference_template(request, template):
PageLevelMessages
.
register_error_message
(
request
,
_
(
'This is a test error'
))
return
render_to_response
(
template
,
context
)
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
return
HttpResponseNotFound
(
'Missing template {template}'
.
format
(
template
=
template
))
openedx/core/lib/derived.py
View file @
fdc50c3a
...
...
@@ -17,21 +17,23 @@ def derived(*settings):
Can be called multiple times to add more derived settings.
Args:
settings (
list): List of s
etting names to register.
settings (
str): S
etting names to register.
"""
__DERIVED
.
extend
(
settings
)
def
derived_
dict_entry
(
setting_dict
,
key
):
def
derived_
collection_entry
(
collection_name
,
*
accessors
):
"""
Registers a setting which is a dictionary
and needs a derived value for a particular ke
y.
Registers a setting which is a dictionary
or list and needs a derived value for a particular entr
y.
Can be called multiple times to add more derived settings.
Args:
setting_dict (str): Name of setting which contains a dictionary.
key (str): Name of key in the setting dictionary which will be derived.
collection_name (str): Name of setting which contains a dictionary or list.
accessors (int|str): Sequence of dictionary keys and list indices in the collection (and
collections within it) leading to the value which will be derived.
For example: 0, 'DIRS'.
"""
__DERIVED
.
append
((
setting_dict
,
key
))
__DERIVED
.
append
((
collection_name
,
accessors
))
def
derive_settings
(
module_name
):
...
...
@@ -52,13 +54,16 @@ def derive_settings(module_name):
elif
isinstance
(
derived
,
tuple
):
# If a tuple, two elements are expected - else ignore.
if
len
(
derived
)
==
2
:
# Both elements are expected to be strings.
# The first string is the attribute which is expected to be a dictionary.
# The second string is a key in that dictionary containing a derived setting.
setting
=
getattr
(
module
,
derived
[
0
])[
derived
[
1
]]
# The first element is the name of the attribute which is expected to be a dictionary or list.
# The second element is a list of string keys in that dictionary leading to a derived setting.
collection
=
getattr
(
module
,
derived
[
0
])
accessors
=
derived
[
1
]
for
accessor
in
accessors
[:
-
1
]:
collection
=
collection
[
accessor
]
setting
=
collection
[
accessors
[
-
1
]]
if
callable
(
setting
):
setting_val
=
setting
(
module
)
getattr
(
module
,
derived
[
0
])
.
update
({
derived
[
1
]:
setting_val
})
collection
[
accessors
[
-
1
]]
=
setting_val
def
clear_for_tests
():
...
...
openedx/core/lib/tests/test_derived.py
View file @
fdc50c3a
...
...
@@ -4,7 +4,7 @@ Tests for derived.py
import
sys
from
unittest
import
TestCase
from
openedx.core.lib.derived
import
derived
,
derive_settings
,
clear_for_tests
from
openedx.core.lib.derived
import
derived
,
derive
d_collection_entry
,
derive
_settings
,
clear_for_tests
class
TestDerivedSettings
(
TestCase
):
...
...
@@ -22,7 +22,9 @@ class TestDerivedSettings(TestCase):
derived
(
'DERIVED_VALUE'
,
'ANOTHER_DERIVED_VALUE'
)
self
.
module
.
DICT_VALUE
=
{}
self
.
module
.
DICT_VALUE
[
'test_key'
]
=
lambda
settings
:
settings
.
DERIVED_VALUE
*
3
derived
((
'DICT_VALUE'
,
'test_key'
))
derived_collection_entry
(
'DICT_VALUE'
,
'test_key'
)
self
.
module
.
DICT_VALUE
[
'list_key'
]
=
[
'not derived'
,
lambda
settings
:
settings
.
DERIVED_VALUE
]
derived_collection_entry
(
'DICT_VALUE'
,
'list_key'
,
1
)
def
test_derived_settings_are_derived
(
self
):
derive_settings
(
__name__
)
...
...
@@ -42,3 +44,7 @@ class TestDerivedSettings(TestCase):
def
test_derived_dict_settings
(
self
):
derive_settings
(
__name__
)
self
.
assertEqual
(
self
.
module
.
DICT_VALUE
[
'test_key'
],
'mutter paneermutter paneermutter paneer'
)
def
test_derived_nested_settings
(
self
):
derive_settings
(
__name__
)
self
.
assertEqual
(
self
.
module
.
DICT_VALUE
[
'list_key'
][
1
],
'mutter paneer'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment