Lints and final tweaks
This commit is contained in:
@@ -44,6 +44,7 @@ MANUAL_ENROLLMENT_ROLE_CHOICES = configuration_helpers.get_value(
|
||||
|
||||
COURSE_DASHBOARD_PLUGIN_VIEW_NAME = "course_dashboard"
|
||||
|
||||
|
||||
def create_manual_enrollment_audit(
|
||||
enrolled_by,
|
||||
user_email,
|
||||
|
||||
@@ -195,7 +195,7 @@ class::
|
||||
# Key is the view that the app wishes to add context to and the value
|
||||
# is the function within the app that will return additional context
|
||||
# when called with the original context
|
||||
PluginContexts.VIEWS.STUDENT_DASHBOARD: u'my_app.context_api.get_dashboard_context'
|
||||
u'course_dashboard': u'my_app.context_api.get_dashboard_context'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,7 +233,7 @@ OR use string constants when they cannot import from djangoapps.plugins::
|
||||
},
|
||||
u'view_context_config': {
|
||||
u'lms.djangoapp': {
|
||||
'student_dashboard': u'my_app.context_api.get_dashboard_context'
|
||||
'course_dashboard': u'my_app.context_api.get_dashboard_context'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ class PluginSignals(object):
|
||||
RELATIVE_PATH = u'relative_path'
|
||||
DEFAULT_RELATIVE_PATH = u'signals'
|
||||
|
||||
|
||||
class PluginContexts(object):
|
||||
"""
|
||||
The PluginContexts enum defines dictionary field names (and defaults)
|
||||
|
||||
@@ -7,7 +7,7 @@ Draft
|
||||
|
||||
Context
|
||||
=======
|
||||
edx-platform contains a plugin system which allows new Django apps to be installed inside the LMS and Studio without requiring the LMS/Studio to know about them. This is what enables us to move to a small and extensible core. While we had the ability to add settings, URLs, and signal handlers in our plugins, there wasn't any way for a plugin to affect the commonly used pages that the core was delivering. Thus a plugin couldn't change any details on the dashboard, courseware, or any other rendered page that the platform delivered.
|
||||
edx-platform contains a plugin system (https://github.com/edx/edx-platform/tree/master/openedx/core/djangoapps/plugins) which allows new Django apps to be installed inside the LMS and Studio without requiring the LMS/Studio to know about them. This is what enables us to move to a small and extensible core. While we had the ability to add settings, URLs, and signal handlers in our plugins, there wasn't any way for a plugin to affect the commonly used pages that the core was delivering. Thus a plugin couldn't change any details on the dashboard, courseware, or any other rendered page that the platform delivered.
|
||||
|
||||
Decisions
|
||||
=========
|
||||
@@ -34,7 +34,7 @@ In the plugin app
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Config
|
||||
++++++
|
||||
Inside of your AppConfig your new plugin app, add a "view_context_config" item like below.
|
||||
Inside of the AppConfig of your new plugin app, add a "view_context_config" item like below.
|
||||
* The format will be {"globally_unique_view_name": "function_inside_plugin_app"}
|
||||
* The function name & path don't need to be named anything specific, so long as they work
|
||||
* These functions will be called on **every** render of that view, so keep them efficient or memoize them if they aren't user specific.
|
||||
@@ -57,7 +57,7 @@ The function that will be called by the plugin system should accept a single par
|
||||
|
||||
Example:
|
||||
::
|
||||
def my_context_function(existing_context):
|
||||
def my_context_function(existing_context, *args, **kwargs):
|
||||
additional_context = {"some_plugin_value": 10}
|
||||
if existing_context.get("some_core_value"):
|
||||
additional_context.append({"some_other_plugin_value": True})
|
||||
@@ -9,19 +9,30 @@ from . import constants, registry
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
def get_plugins_view_context(project_type, view_name, existing_context={}):
|
||||
|
||||
def get_plugins_view_context(project_type, view_name, existing_context=None):
|
||||
"""
|
||||
Returns a dict of additonal view context. Will check if any plugin apps
|
||||
Returns a dict of additional view context. Will check if any plugin apps
|
||||
have that view in their view_context_config, and if so will call their
|
||||
selected function to get their context dicts.
|
||||
|
||||
Params:
|
||||
project_type: a string that determines which project (lms or studio) the view is being called in. See the
|
||||
ProjectType enum in plugins/constants.py for valid options
|
||||
view_name: a string that determines which view needs the additional context. These are globally unique and
|
||||
noted in the api.py in the view's app.
|
||||
existing_context: a dictionary which includes all of the data that the page was going to render with prior
|
||||
to the addition of each plugin's context. This is what will be passed to plugins so they may choose
|
||||
what data to add to the view.
|
||||
"""
|
||||
aggregate_context = {"plugins": {}}
|
||||
|
||||
# This functionality is cached
|
||||
context_functions = _get_context_functions_for_view(project_type, view_name)
|
||||
if existing_context is None:
|
||||
existing_context = {}
|
||||
|
||||
context_functions = _get_cached_context_functions_for_view(project_type, view_name)
|
||||
|
||||
for (context_function, plugin_name) in context_functions:
|
||||
plugin_context = context_function(existing_context)
|
||||
try:
|
||||
plugin_context = context_function(existing_context)
|
||||
except Exception as exc:
|
||||
@@ -37,14 +48,8 @@ def get_plugins_view_context(project_type, view_name, existing_context={}):
|
||||
return aggregate_context
|
||||
|
||||
|
||||
def _get_context_function(app_config, project_type, view_name):
|
||||
plugin_config = getattr(app_config, constants.PLUGIN_APP_CLASS_ATTRIBUTE_NAME, {})
|
||||
context_config = plugin_config.get(constants.PluginContexts.CONFIG, {})
|
||||
project_type_settings = context_config.get(project_type, {})
|
||||
return project_type_settings.get(view_name)
|
||||
|
||||
@process_cached
|
||||
def _get_context_functions_for_view(project_type, view_name):
|
||||
def _get_cached_context_functions_for_view(project_type, view_name):
|
||||
"""
|
||||
Returns a list of tuples where the first item is the context function
|
||||
and the second item is the name of the plugin it's being called from.
|
||||
@@ -55,7 +60,7 @@ def _get_context_functions_for_view(project_type, view_name):
|
||||
"""
|
||||
context_functions = []
|
||||
for app_config in registry.get_app_configs(project_type):
|
||||
context_function_path = _get_context_function(app_config, project_type, view_name)
|
||||
context_function_path = _get_context_function_path(app_config, project_type, view_name)
|
||||
if context_function_path:
|
||||
module_path, _, name = context_function_path.rpartition('.')
|
||||
try:
|
||||
@@ -79,3 +84,10 @@ def _get_context_functions_for_view(project_type, view_name):
|
||||
view_name
|
||||
)
|
||||
return context_functions
|
||||
|
||||
|
||||
def _get_context_function_path(app_config, project_type, view_name):
|
||||
plugin_config = getattr(app_config, constants.PLUGIN_APP_CLASS_ATTRIBUTE_NAME, {})
|
||||
context_config = plugin_config.get(constants.PluginContexts.CONFIG, {})
|
||||
project_type_settings = context_config.get(project_type, {})
|
||||
return project_type_settings.get(view_name)
|
||||
|
||||
Reference in New Issue
Block a user