A Django reusable app providing support for LTI Advantage.
Install using pip.
pip install django-lti
Start by adding lti_tool
to your project's INSTALLED_APPS
.
INSTALLED_APPS = [
...
"lti_tool",
]
Then, add lti_tool.middleware.LtiLaunchMiddleware
to the MIDDLEWARE
setting.
It's important to list the LtiLaunchMiddleware
after SessionMiddleware
.
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'lti_tool.middleware.LtiLaunchMiddleware',
]
Finally, run migrations to initialize the needed database tables.
python manage.py migrate lti_tool
To allow LTI platforms to retrieve a JWKS and initiate a launch, add paths for
lti_tool.views.jwks
and lti_tool.views.OIDCLoginInitView
to urls.py
...
from lti_tool.views import jwks, OIDCLoginInitView
urlpatterns = [
path(".well-known/jwks.json", jwks, name="jwks"),
path("init/<uuid:registration_uuid>/", OIDCLoginInitView.as_view(), name="init"),
]
Keys for the JWKS can be generated using the rotate_keys
management command.
python manage.py rotate_keys
An LTI platform can be registered through the Django admin, or using a custom interface.
To handle the LTI launch, inherit from LtiLaunchBaseView
and implement the handler
methods for the types of LTI message types that the application supports.
class ApplicationLaunchView(LtiLaunchBaseView):
def handle_resource_launch(self, request, lti_launch):
... # Required. Typically redirects the users to the appropriate page.
def handle_deep_linking_launch(self, request, lti_launch):
... # Optional.
def handle_submission_review_launch(self, request, lti_launch):
... # Optional.
def handle_data_privacy_launch(self, request, lti_launch):
... # Optional.
Each handler method receives the request, as well as a LtiLaunch
object.
When a session is initiated by an LTI launch, data about the launch is available from
the request at request.lti_launch
as an LtiLaunch
object. During a non-LTI session
request.lti_launch
will refer to an AbsentLtiLaunch
object.
It is possible to distinguish between LtiLaunch
and AbsentLtiLaunch
objects using
the .is_present
and .is_absent
properties.