Lints and final tweaks

This commit is contained in:
Matt Tuchfarber
2020-03-17 22:19:22 -04:00
parent 8a48218628
commit 0a8b06a122
5 changed files with 32 additions and 18 deletions

View File

@@ -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,

View File

@@ -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'
}
}
}

View File

@@ -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)

View File

@@ -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})

View File

@@ -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)