openedx.core.djangoapps.content_libraries package#

Subpackages#

Submodules#

openedx.core.djangoapps.content_libraries.api module#

Python API for content libraries#

Via views.py, most of these API methods are also exposed as a REST API.

The API methods in this file are focused on authoring and specific to content libraries; they wouldn’t necessarily apply or work in other learning contexts such as courses, blogs, “pathways,” etc.

** As this is an authoring-focused API, all API methods in this file deal with the DRAFT version of the content library.**

Some of these methods will work and may be used from the LMS if needed (mostly for test setup; other use is discouraged), but some of the implementation details rely on Studio so other methods will raise errors if called from the LMS. (The REST API is not available at all from the LMS.)

Any APIs that use/affect content libraries but are generic enough to work in other learning contexts too are in the core XBlock python/REST API at openedx.core.djangoapps.xblock.api/rest_api.

For example, to render a content library XBlock as HTML, one can use the generic:

render_block_view(block, view_name, user)

That is an API in openedx.core.djangoapps.xblock.api (use it from Studio for the draft version, from the LMS for published version).

There are one or two methods in this file that have some overlap with the core XBlock API; for example, this content library API provides a get_library_block() which returns metadata about an XBlock; it’s in this API because it also returns data about whether or not the XBlock has unpublished edits, which is an authoring-only concern. Likewise, APIs for getting/setting an individual XBlock’s OLX directly seem more appropriate for small, reusable components in content libraries and may not be appropriate for other learning contexts so they are implemented here in the library API only. In the future, if we find a need for these in most other learning contexts then those methods could be promoted to the core XBlock API and made generic.

Import from Courseware#

Content Libraries can import blocks from Courseware (Modulestore). The import can be done per-course, by listing its content, and supports both access to remote platform instances as well as local modulestore APIs. Additionally, there are Celery-based interfaces suitable for background processing controlled through RESTful APIs (see views).

class openedx.core.djangoapps.content_libraries.api.AccessLevel#

Bases: object

Enum defining library access levels/permissions

ADMIN_LEVEL = 'admin'#
AUTHOR_LEVEL = 'author'#
NO_ACCESS = None#
READ_LEVEL = 'read'#
class openedx.core.djangoapps.content_libraries.api.BaseEdxImportClient(library_key=None, library=None, use_course_key_as_block_id_suffix=True)#

Bases: ABC

Base class for all courseware import clients.

Import clients are wrappers tailored to implement the steps used in the import APIs and can leverage different backends. It is not aimed towards being a generic API client for Open edX.

EXPORTABLE_BLOCK_TYPES = {'drag-and-drop-v2', 'html', 'problem', 'video'}#
abstract get_block_data(block_key)#

Get the block’s OLX and static files, if any.

abstract get_block_static_data(asset_file)#

Get the contents of an asset_file..

abstract get_export_keys(course_key)#

Get all exportable block keys of a given course.

import_block(modulestore_key)#

Import a single modulestore block.

import_blocks_from_course(course_key, progress_callback)#

Import all eligible blocks from course key.

Progress is reported through progress_callback, guaranteed to be called within an exception handler if exception is not None.

exception openedx.core.djangoapps.content_libraries.api.BlockLimitReachedError#

Bases: Exception

Maximum number of allowed XBlocks in the library reached

exception openedx.core.djangoapps.content_libraries.api.ContentLibraryBlockNotFound(usage_id)#

Bases: XBlockNotFoundError

XBlock not found in the content library

class openedx.core.djangoapps.content_libraries.api.ContentLibraryMetadata(key: LibraryLocatorV2, title='', description='', num_blocks=0, version=0, type='complex', last_published: datetime | None = None, has_unpublished_changes=False, has_unpublished_deletes=False, allow_lti=False, allow_public_learning=False, allow_public_read=False, license='')#

Bases: object

Class that represents the metadata about a content library.

class openedx.core.djangoapps.content_libraries.api.ContentLibraryPermissionEntry(user: AbstractUser | None = None, group: Group | None = None, access_level=None)#

Bases: object

A user or group granted permission to use a content library.

class openedx.core.djangoapps.content_libraries.api.EdxApiImportClient(lms_url, studio_url, oauth_key, oauth_secret, *args, **kwargs)#

Bases: BaseEdxImportClient

An import client based on a remote Open Edx API interface.

TODO: Look over this class. We’ll probably need to completely re-implement the import process.

URL_COURSES = '/api/courses/v1/courses/{course_key}'#
URL_MODULESTORE_BLOCK_OLX = '/api/olx-export/v1/xblock/{block_key}/'#
get_block_data(block_key)#

See parent’s docstring.

get_block_static_data(asset_file)#

See parent’s docstring.

get_export_keys(course_key)#

See parent’s docstring.

class openedx.core.djangoapps.content_libraries.api.EdxModulestoreImportClient(modulestore_instance=None, **kwargs)#

Bases: BaseEdxImportClient

An import client based on the local instance of modulestore.

get_block_data(block_key)#

Get block OLX by serializing it from modulestore directly.

get_block_static_data(asset_file)#

Get static content from its URL if available, otherwise from its data.

get_export_keys(course_key)#

Retrieve the course from modulestore and traverse its content tree.

exception openedx.core.djangoapps.content_libraries.api.IncompatibleTypesError#

Bases: Exception

Library type constraint violated

exception openedx.core.djangoapps.content_libraries.api.InvalidNameError#

Bases: ValueError

The specified name/identifier is not valid

exception openedx.core.djangoapps.content_libraries.api.LibraryAlreadyExists#

Bases: KeyError

A library with the specified slug already exists

exception openedx.core.djangoapps.content_libraries.api.LibraryBlockAlreadyExists#

Bases: KeyError

An XBlock with that ID already exists in the library

exception openedx.core.djangoapps.content_libraries.api.LibraryPermissionIntegrityError#

Bases: IntegrityError

Thrown when an operation would cause insane permissions.

class openedx.core.djangoapps.content_libraries.api.LibraryXBlockMetadata(usage_key: LibraryUsageLocatorV2, display_name='', has_unpublished_changes=False, tags_count=0)#

Bases: object

Class that represents the metadata about an XBlock in a content library.

classmethod from_component(library_key, component)#

Construct a LibraryXBlockMetadata from a Component object.

class openedx.core.djangoapps.content_libraries.api.LibraryXBlockStaticFile(path='', url='', size=0)#

Bases: object

Class that represents a static file in a content library, associated with a particular XBlock.

class openedx.core.djangoapps.content_libraries.api.LibraryXBlockType(block_type='', display_name='')#

Bases: object

An XBlock type that can be added to a content library

openedx.core.djangoapps.content_libraries.api.add_library_block_static_asset_file(usage_key, file_name, file_content) LibraryXBlockStaticFile#

Upload a static asset file into the library, to be associated with the specified XBlock. Will silently overwrite an existing file of the same name.

file_name should be a name like “doc.pdf”. It may optionally contain slashes

like ‘en/doc.pdf’

file_content should be a binary string.

Returns a LibraryXBlockStaticFile object.

Sends a LIBRARY_BLOCK_UPDATED event.

Example

video_block = UsageKey.from_string(“lb:VideoTeam:python-intro:video:1”) add_library_block_static_asset_file(video_block, “subtitles-en.srt”, subtitles.encode(‘utf-8’))

openedx.core.djangoapps.content_libraries.api.create_library(org, slug, title, description='', allow_public_learning=False, allow_public_read=False, library_license='', library_type='complex')#

Create a new content library.

org: an organizations.models.Organization instance

slug: a slug for this library like ‘physics-problems’

title: title for this library

description: description of this library

allow_public_learning: Allow anyone to read/learn from blocks in the LMS

allow_public_read: Allow anyone to view blocks (including source) in Studio?

library_type: Deprecated parameter, not really used. Set to COMPLEX.

Returns a ContentLibraryMetadata instance.

openedx.core.djangoapps.content_libraries.api.create_library_block(library_key, block_type, definition_id)#

Create a new XBlock in this library of the specified type (e.g. “html”).

openedx.core.djangoapps.content_libraries.api.delete_library(library_key)#

Delete a content library

openedx.core.djangoapps.content_libraries.api.delete_library_block(usage_key, remove_from_parent=True)#

Delete the specified block from this library (soft delete).

openedx.core.djangoapps.content_libraries.api.delete_library_block_static_asset_file(usage_key, file_name)#

Delete a static asset file from the library.

Sends a LIBRARY_BLOCK_UPDATED event.

Example

video_block = UsageKey.from_string(“lb:VideoTeam:python-intro:video:1”) delete_library_block_static_asset_file(video_block, “subtitles-en.srt”)

openedx.core.djangoapps.content_libraries.api.get_allowed_block_types(library_key)#

Get a list of XBlock types that can be added to the specified content library.

openedx.core.djangoapps.content_libraries.api.get_libraries_for_user(user, org=None, library_type=None, text_search=None)#

Return content libraries that the user has permission to view.

openedx.core.djangoapps.content_libraries.api.get_library(library_key)#

Get the library with the specified key. Does not check permissions. returns a ContentLibraryMetadata instance.

Raises ContentLibraryNotFound if the library doesn’t exist.

openedx.core.djangoapps.content_libraries.api.get_library_block(usage_key) LibraryXBlockMetadata#

Get metadata about (the draft version of) one specific XBlock in a library.

This will raise ContentLibraryBlockNotFound if there is no draft version of this block (i.e. it’s been soft-deleted from Studio), even if there is a live published version of it in the LMS.

openedx.core.djangoapps.content_libraries.api.get_library_block_static_asset_files(usage_key) list[LibraryXBlockStaticFile]#

Given an XBlock in a content library, list all the static asset files associated with that XBlock.

Returns a list of LibraryXBlockStaticFile objects, sorted by path.

TODO: This is not yet implemented for Learning Core backed libraries. TODO: Should this be in the general XBlock API rather than the libraries API?

openedx.core.djangoapps.content_libraries.api.get_library_components(library_key, text_search=None, block_types=None) QuerySet#

Get the library components and filter.

TODO: Full text search needs to be implemented as a custom lookup for MySQL, but it should have a fallback to still work in SQLite.

openedx.core.djangoapps.content_libraries.api.get_library_team(library_key)#

Get the list of users/groups granted permission to use this library.

openedx.core.djangoapps.content_libraries.api.get_library_user_permissions(library_key, user)#

Fetch the specified user’s access information. Will return None if no permissions have been granted.

openedx.core.djangoapps.content_libraries.api.get_metadata(queryset, text_search=None)#

Take a list of ContentLibrary objects and return metadata from Learning Core.

openedx.core.djangoapps.content_libraries.api.get_or_create_olx_media_type(block_type: str) MediaType#

Get or create a MediaType for the block type.

Learning Core stores all Content with a Media Type (a.k.a. MIME type). For OLX, we use the “application/vnd.*” convention, per RFC 6838.

openedx.core.djangoapps.content_libraries.api.get_v1_or_v2_library(library_id: str | LibraryLocatorV1 | LibraryLocatorV2, version: str | int | None) LibraryRootV1 | ContentLibraryMetadata | None#

Fetch either a V1 or V2 content library from a V1/V2 key (or key string) and version.

V1 library versions are Mongo ObjectID strings. V2 library versions can be positive ints, or strings of positive ints. Passing version=None will return the latest version the library.

Returns None if not found. If key is invalid, raises InvalidKeyError. For V1, if key has a version, it is ignored in favor of version. For V2, if version is provided but it isn’t an int or parseable to one, we raise a ValueError.

Examples: * get_v1_or_v2_library(“library-v1:ProblemX+PR0B”, None) -> <LibraryRootV1> * get_v1_or_v2_library(“library-v1:ProblemX+PR0B”, “65ff…”) -> <LibraryRootV1> * get_v1_or_v2_library(“lib:RG:rg-1”, None) -> <ContentLibraryMetadata> * get_v1_or_v2_library(“lib:RG:rg-1”, “36”) -> <ContentLibraryMetadata> * get_v1_or_v2_library(“lib:RG:rg-1”, “xyz”) -> <ValueError> * get_v1_or_v2_library(“notakey”, “xyz”) -> <InvalidKeyError>

If you just want to get a V2 library, use get_library instead.

openedx.core.djangoapps.content_libraries.api.import_blocks_create_task(library_key, course_key, use_course_key_as_block_id_suffix=True)#

Create a new import block task.

This API will schedule a celery task to perform the import, and it returns a import task object for polling.

openedx.core.djangoapps.content_libraries.api.publish_changes(library_key)#

Publish all pending changes to the specified library.

openedx.core.djangoapps.content_libraries.api.require_permission_for_library_key(library_key, user, permission)#

Given any of the content library permission strings defined in openedx.core.djangoapps.content_libraries.permissions, check if the given user has that permission for the library with the specified library ID.

Raises django.core.exceptions.PermissionDenied if the user doesn’t have permission.

openedx.core.djangoapps.content_libraries.api.revert_changes(library_key)#

Revert all pending changes to the specified library, restoring it to the last published version.

openedx.core.djangoapps.content_libraries.api.set_library_block_olx(usage_key, new_olx_str)#

Replace the OLX source of the given XBlock.

This is only meant for use by developers or API client applications, as very little validation is done and this can easily result in a broken XBlock that won’t load.

openedx.core.djangoapps.content_libraries.api.set_library_group_permissions(library_key, group, access_level)#

Change the specified group’s level of access to this library.

access_level should be one of the AccessLevel values defined above.

openedx.core.djangoapps.content_libraries.api.set_library_user_permissions(library_key, user, access_level)#

Change the specified user’s level of access to this library.

access_level should be one of the AccessLevel values defined above.

openedx.core.djangoapps.content_libraries.api.update_library(library_key, title=None, description=None, allow_public_learning=None, allow_public_read=None, library_type=None, library_license=None)#

Update a library’s metadata (Slug cannot be changed as it would break IDs throughout the system.)

A value of None means “don’t change”.

openedx.core.djangoapps.content_libraries.apps module#

Django AppConfig for Content Libraries Implementation

class openedx.core.djangoapps.content_libraries.apps.ContentLibrariesConfig(app_name, app_module)#

Bases: AppConfig

Django AppConfig for Content Libraries Implementation

name = 'openedx.core.djangoapps.content_libraries'#
plugin_app = {'settings_config': {'cms.djangoapp': {}}, 'url_config': {'cms.djangoapp': {'namespace': 'content_libraries'}}}#
ready()#

Import signal handler’s module to ensure they are registered.

verbose_name = 'Content Libraries (Blockstore-based)'#

openedx.core.djangoapps.content_libraries.auth module#

Content Library LTI authentication.

This module offers an authentication backend to support LTI launches within content libraries.

class openedx.core.djangoapps.content_libraries.auth.LtiAuthenticationBackend#

Bases: ModelBackend

Authenticate based on content library LTI profile.

The backend assumes the profile was previously created and its presence is enough to assume the launch claims are valid.

authenticate(request, iss=None, aud=None, sub=None, **kwargs)#

Authenticate if the user in the request has an LTI profile.

openedx.core.djangoapps.content_libraries.constants module#

Constants used for the content libraries.

openedx.core.djangoapps.content_libraries.library_context module#

Definition of “Library” as a learning context.

class openedx.core.djangoapps.content_libraries.library_context.LibraryContextImpl(**kwargs)#

Bases: LearningContext

Implements content libraries as a learning context.

This is the new content libraries based on Blockstore, not the old content libraries based on modulestore.

block_exists(usage_key)#

Does the block for this usage_key exist in this Library?

Note that this applies to all versions, i.e. you can put a usage key for a piece of content that has been soft-deleted (removed from Drafts), and it will still return True here. That’s because for the purposes of permission checking, we just want to know whether that block has ever existed in this Library, because we could be looking at any older version of it.

can_edit_block(user, usage_key)#

Does the specified usage key exist in its context, and if so, does the specified user have permission to edit it (make changes to the authored data store)?

user: a Django User object (may be an AnonymousUser)

usage_key: the UsageKeyV2 subclass used for this learning context

Must return a boolean.

can_view_block(user, usage_key)#

Does the specified usage key exist in its context, and if so, does the specified user have permission to view it and interact with it (call handlers, save user state, etc.)?

user: a Django User object (may be an AnonymousUser)

usage_key: the UsageKeyV2 subclass used for this learning context

Must return a boolean.

openedx.core.djangoapps.content_libraries.models module#

Content Libraries Models#

This module contains the models for new Content Libraries.

LTI 1.3 Models#

Content Libraries serves blockstore-based content through LTI 1.3 launches. The interface supports resource link launches and grading services. Two use cases justify the current data model to support LTI launches. They are:

  1. Authentication and authorization. This use case demands management of user lifecycle to authorize access to content and grade submission, and it introduces a model to own the authentication business logic related to LTI.

  2. Grade and assignments. When AGS is supported, content libraries store additional information concerning the launched resource so that, once the grading sub-system submits the score, it can retrieve them to propagate the score update into the LTI platform’s grade book.

Relationship with LMS’s lti_provider` models#

The data model above is similar to the one provided by the current LTI 1.1 implementation for modulestore and courseware content. But, Content Libraries is orthogonal. Its use-case is to offer standalone, embedded content from a specific backend (blockstore). As such, it decouples from LTI 1.1. and the logic assume no relationship or impact across the two applications. The same reasoning applies to steps beyond the data model, such as at the XBlock runtime, authentication, and score handling, etc.

class openedx.core.djangoapps.content_libraries.models.ContentLibrary(*args, **kwargs)#

Bases: Model

A Content Library is a collection of content (XBlocks and/or static assets)

All actual content is stored in Blockstore, and any data that we’d want to transfer to another instance if this library were exported and then re-imported on another Open edX instance should be kept in Blockstore. This model in Studio should only be used to track settings specific to this Open edX instance, like who has permission to edit this content library.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

property allow_lti#

True if there is at least one LTI tool configuration associated if this library.

allow_public_learning#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

allow_public_read#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod authorize_lti_launch(library_key, *, issuer, client_id=None)#

Check if the given Issuer and Client ID are authorized to launch content from this library.

authorized_lti_configs#

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

bundle_uuid#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_license_display(*, field=<django.db.models.fields.CharField: license>)#
get_type_display(*, field=<django.db.models.fields.CharField: type>)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

import_tasks#

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

learning_package#

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

learning_package_id#
property library_key#

Get the LibraryLocatorV2 opaque key for this library

license#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects: ContentLibraryManager = <openedx.core.djangoapps.content_libraries.models.ContentLibraryManager object>#
org#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

org_id#
permission_grants#

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

slug#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

type#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx.core.djangoapps.content_libraries.models.ContentLibraryBlockImportTask(*args, **kwargs)#

Bases: Model

Model of a task to import blocks from an external source (e.g. modulestore).

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

TASK_CREATED = 'created'#
TASK_FAILED = 'failed'#
TASK_PENDING = 'pending'#
TASK_RUNNING = 'running'#
TASK_STATE_CHOICES = (('created', 'Task was created, but not queued to run.'), ('pending', 'Task was created and queued to run.'), ('running', 'Task is running.'), ('failed', 'Task finished, but some blocks failed to import.'), ('successful', 'Task finished successfully.'))#
TASK_SUCCESSFUL = 'successful'#
course_id#

DO NOT REUSE THIS CLASS. Provided for backwards compatibility only!

A placeholder class that provides a way to set the attribute on the model.

created_at#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod execute(import_task_id)#

A context manager to manage a task that is being executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)#
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)#
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)#
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)#
get_state_display(*, field=<django.db.models.fields.CharField: state>)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

library#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

library_id#
objects = <django.db.models.manager.Manager object>#
progress#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

save_progress(progress)#
state#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

updated_at#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx.core.djangoapps.content_libraries.models.ContentLibraryManager(*args, **kwargs)#

Bases: Manager

Custom manager for ContentLibrary class.

get_by_key(library_key)#

Get the ContentLibrary for the given LibraryLocatorV2 key.

class openedx.core.djangoapps.content_libraries.models.ContentLibraryPermission(*args, **kwargs)#

Bases: Model

Row recording permissions for a content library

ACCESS_LEVEL_CHOICES = (('admin', 'Administer users and author content'), ('author', 'Author content'), ('read', 'Read-only'))#
ADMIN_LEVEL = 'admin'#
AUTHOR_LEVEL = 'author'#
exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

READ_LEVEL = 'read'#
access_level#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_access_level_display(*, field=<django.db.models.fields.CharField: access_level>)#
group#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

group_id#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

library#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

library_id#
objects = <django.db.models.manager.Manager object>#
save(*args, **kwargs)#

Validate any constraints on the model.

We can remove this and replace it with a proper database constraint once we’re upgraded to Django 2.2+

user#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

user_id#
class openedx.core.djangoapps.content_libraries.models.LtiGradedResource(*args, **kwargs)#

Bases: Model

A content libraries resource launched through LTI with AGS enabled.

Essentially, an instance of this model represents a successful LTI AGS launch. This model links the profile that launched the resource with the resource itself, allowing identifcation of the link through its usage key string and user id.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

ags_lineitem#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <openedx.core.djangoapps.content_libraries.models.LtiGradedResourceManager object>#
profile#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

profile_id#
resource_id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

resource_title#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

update_score(weighted_earned, weighted_possible, timestamp)#

Use LTI’s score service to update the LTI platform’s gradebook.

This method synchronously send a request to the LTI platform to update the assignment score.

usage_key#

DO NOT REUSE THIS CLASS. Provided for backwards compatibility only!

A placeholder class that provides a way to set the attribute on the model.

class openedx.core.djangoapps.content_libraries.models.LtiGradedResourceManager(*args, **kwargs)#

Bases: Manager

A custom manager for the graded resources model.

get_from_user_id(user_id, **kwds)#

Retrieve a resource for a given user id holding an lti profile.

upsert_from_ags_launch(user, block, resource_endpoint, resource_link)#

Update or create a graded resource at AGS launch.

class openedx.core.djangoapps.content_libraries.models.LtiProfile(*args, **kwargs)#

Bases: Model

Content Libraries LTI’s profile for Open edX users.

Unless Anonymous, this should be a unique representation of the LTI subject (as per the client token sub identify claim) that initiated an LTI launch through Content Libraries.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

client_id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

created_at#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)#
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

lti_resources#

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

objects = <openedx.core.djangoapps.content_libraries.models.LtiProfileManager object>#
platform_id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

save(*args, **kwds)#

Get or create an edx user on save.

subject_id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property subject_url#

An local URL that is known to uniquely identify this profile.

We take advantage of the fact that platform id is required to be an URL and append paths with the reamaining keys to it.

user#

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

user_id#
class openedx.core.djangoapps.content_libraries.models.LtiProfileManager(*args, **kwargs)#

Bases: Manager

Custom manager of LtiProfile mode.

get_from_claims(*, iss, aud, sub)#

Get the an instance from a LTI launch claims.

get_or_create_from_claims(*, iss, aud, sub)#

Get or create an instance from a LTI launch claims.

openedx.core.djangoapps.content_libraries.permissions module#

Permissions for Content Libraries (v2, Blockstore-based)

openedx.core.djangoapps.content_libraries.serializers module#

Serializers for the content libraries REST API

class openedx.core.djangoapps.content_libraries.serializers.BaseFilterSerializer(*args, **kwargs)#

Bases: Serializer

Base serializer for filtering listings on the content library APIs.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryAddPermissionByEmailSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for adding a new user and granting their access level via their email address.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryBlockImportTaskCreateSerializer(*args, **kwargs)#

Bases: Serializer

Serializer to create a new block import task.

The serializer accepts the following parameter:

  • The courseware course key to import blocks from.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryBlockImportTaskSerializer(*args, **kwargs)#

Bases: ModelSerializer

Serializer for a Content Library block import task.

class Meta#

Bases: object

fields = '__all__'#
model#

alias of ContentLibraryBlockImportTask

get_org(obj)#
class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryFilterSerializer(*args, **kwargs)#

Bases: BaseFilterSerializer

Serializer for filtering library listings.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryMetadataSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for ContentLibraryMetadata

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryPermissionLevelSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for the “Access Level” of a ContentLibraryPermission object.

This is used when updating a user or group’s permissions re some content library.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryPermissionSerializer(*args, **kwargs)#

Bases: ContentLibraryPermissionLevelSerializer

Serializer for a ContentLibraryPermission object, which grants either a user or a group permission to view a content library.

class openedx.core.djangoapps.content_libraries.serializers.ContentLibraryUpdateSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for updating an existing content library

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockCreationSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for adding a new XBlock to a content library

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockMetadataSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for LibraryXBlockMetadata

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockOlxSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for representing an XBlock’s OLX

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockStaticFileSerializer(*args, **kwargs)#

Bases: Serializer

Serializer representing a static file associated with an XBlock

Serializes a LibraryXBlockStaticFile (or a BundleFile)

to_representation(instance)#

Generate the serialized representation of this static asset file.

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockStaticFilesSerializer(*args, **kwargs)#

Bases: Serializer

Serializer representing a static file associated with an XBlock

Serializes a LibraryXBlockStaticFile (or a BundleFile)

class openedx.core.djangoapps.content_libraries.serializers.LibraryXBlockTypeSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for LibraryXBlockType

openedx.core.djangoapps.content_libraries.signal_handlers module#

Content library signal handlers.

openedx.core.djangoapps.content_libraries.signal_handlers.score_changed_handler(sender, **kwargs)#

Match the score event to an LTI resource and update.

openedx.core.djangoapps.content_libraries.tasks module#

Celery tasks for Content Libraries.

Architecture note:

Several functions in this file manage the copying/updating of blocks in modulestore and blockstore. These operations should only be performed within the context of CMS. However, due to existing edx-platform code structure, we’ve had to define the functions in shared source tree (openedx/) and the tasks are registered in both LMS and CMS.

To ensure that we’re not accidentally importing things from blockstore in the LMS context, we use ensure_cms throughout this module.

A longer-term solution to this issue would be to move the content_libraries app to cms: openedx/edx-platform#33428

class openedx.core.djangoapps.content_libraries.tasks.LibrarySyncChildrenTask#

Bases: UserTask

Base class for tasks which operate upon library_content children.

classmethod generate_name(arguments_dict) str#

Create a name for this particular import task instance.

Should be both: a. semi human-friendly b. something we can query in order to determine whether the dest block has a task in progress

Parameters:

arguments_dict (dict) – The arguments given to the task function

ignore_result = False#

If enabled the worker won’t store task state and return values for this task. Defaults to the :setting:`task_ignore_result` setting.

priority = None#

Default task priority.

rate_limit = None#

None (no rate limit), ‘100/s’ (hundred tasks a second), ‘100/m’ (hundred tasks a minute),`’100/h’` (hundred tasks an hour)

Type:

Rate limit for this task type. Examples

reject_on_worker_lost = None#

Even if acks_late is enabled, the worker will acknowledge tasks when the worker process executing them abruptly exits or is signaled (e.g., :sig:`KILL`/:sig:`INT`, etc).

Setting this to true allows the message to be re-queued instead, so that the task will execute again by the same worker, or another worker.

Warning: Enabling this can cause message loops; make sure you know what you’re doing.

request_stack = <celery.utils.threads._LocalStack object>#

Task request stack, the current request will be the topmost.

serializer = 'json'#

The name of a serializer that are registered with kombu.serialization.registry. Default is ‘json’.

store_errors_even_if_ignored = True#

When enabled errors will be stored even if the task is otherwise configured to ignore results.

track_started = True#

If enabled the task will report its status as ‘started’ when the task is executed by a worker. Disabled by default as the normal behavior is to not report that level of granularity. Tasks are either pending, finished, or waiting to be retried.

Having a ‘started’ status can be useful for when there are long running tasks and there’s a need to report what task is currently running.

The application default can be overridden using the :setting:`task_track_started` setting.

typing = True#

Enable argument checking. You can set this to false if you don’t want the signature to be checked when calling the task. Defaults to app.strict_typing.

openedx.core.djangoapps.content_libraries.urls module#

URL configuration for Studio’s Content Libraries REST API

openedx.core.djangoapps.content_libraries.views module#

Content Libraries Views#

This module contains the REST APIs for Learning Core-based content libraries, and LTI 1.3 views (though I’m not sure how functional the LTI piece of this is right now).

Most of the real work is intended to happen in the api.py module. The views are intended to be thin ones that do:

  1. Permissions checking

  2. Input/output data conversion via serializers

  3. Pagination

Everything else should be delegated to api.py for the actual business logic. If you see business logic happening in these views, consider refactoring them into the api module instead.

Warning

NOTICE: DO NOT USE THE @atomic DECORATOR FOR THESE VIEWS!!!

Views in ths module are decorated with:

@method_decorator(non_atomic_requests, name=”dispatch”)

This forces the views to execute without an implicit view-level transaction, even if the project is configured to use view-level transactions by default. (So no matter what you set the ATOMIC_REQUESTS setting to.)

We must use manual transactions for content libraries related views, or we’ll run into mysterious race condition bugs. We should NOT use the @atomic decorator over any of these views.

The problem is this: Code outside of this app will want to listen for content lifecycle events like LIBRARY_BLOCK_CREATED and take certain actions based on them. We see this pattern used extensively with courses. Another common pattern is to use celery to queue up an asynchronous task to do that work.

If there is an implicit database transaction around the entire view execution, the celery task may start up just before the view finishes executing. When that happens, the celery task doesn’t see the new content change, because the view transaction hasn’t finished committing it to the database yet.

The worst part of this is that dev environments and tests often won’t catch this because celery is typically configured to run in-process in those situations. When it’s run in-process, celery is already inside the view’s transaction so it will “see” the new changes and everything will appear to be fine–only to fail intermittently when deployed to production.

We can and should continue to use atomic() as a context manager when we want to make changes to multiple models. But this should happen at the api module layer, not in the view. Other apps are permitted to call functions in the public api.py module, and we want to make sure those api calls manage their own transactions and don’t assume that they’re being called in an atomic block.

Historical note: These views used to be wrapped with @atomic because we wanted to make all views that operated on Blockstore data atomic:

class openedx.core.djangoapps.content_libraries.views.LibraryApiPagination#

Bases: PageNumberPagination

Paginates over ContentLibraryMetadata objects.

apidoc_params = [Parameter([('name', 'pagination'), ('in', 'query'), ('description', 'Enables paginated schema'), ('type', 'boolean')]), Parameter([('name', 'page'), ('in', 'query'), ('description', 'Page number of result. Defaults to 1'), ('type', 'integer')]), Parameter([('name', 'page_size'), ('in', 'query'), ('description', 'Page size of the result. Defaults to 50'), ('type', 'integer')])]#
page_size = 50#
page_size_query_param = 'page_size'#
class openedx.core.djangoapps.content_libraries.views.LibraryBlockAssetListView(**kwargs)#

Bases: APIView

Views to list an existing XBlock’s static asset files

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, usage_key_str)#

List the static asset files belonging to this block.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class openedx.core.djangoapps.content_libraries.views.LibraryBlockAssetView(**kwargs)#

Bases: APIView

Views to work with an existing XBlock’s static asset files

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, usage_key_str, file_path)#

Delete a static asset file belonging to this block.

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, usage_key_str, file_path)#

Get a static asset file belonging to this block.

parser_classes = (<class 'rest_framework.parsers.MultiPartParser'>,)#
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
put(request, usage_key_str, file_path)#

Replace a static asset file belonging to this block.

class openedx.core.djangoapps.content_libraries.views.LibraryBlockLtiUrlView(**kwargs)#

Bases: APIView

Views to generate LTI URL for existing XBlocks in a content library.

Returns 404 in case the block not found by the given key.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, usage_key_str)#

Get the LTI launch URL for the XBlock.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class openedx.core.djangoapps.content_libraries.views.LibraryBlockOlxView(**kwargs)#

Bases: APIView

Views to work with an existing XBlock’s OLX

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, usage_key_str)#

Get the block’s OLX

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
post(request, usage_key_str)#

Replace the block’s OLX.

This API is only meant for use by developers or API client applications. Very little validation is done.

class openedx.core.djangoapps.content_libraries.views.LibraryBlockTypesView(**kwargs)#

Bases: APIView

View to get the list of XBlock types that can be added to this library

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, lib_key_str)#

Get the list of XBlock types that can be added to this library

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class openedx.core.djangoapps.content_libraries.views.LibraryBlockView(**kwargs)#

Bases: APIView

Views to work with an existing XBlock in a content library.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, usage_key_str)#

Delete a usage of a block from the library (and any children it has).

If this is the only usage of the block’s definition within this library, both the definition and the usage will be deleted. If this is only one of several usages, the definition will be kept. Usages by linked bundles are ignored and will not prevent deletion of the definition.

If the usage points to a definition in a linked bundle, the usage will be deleted but the link and the linked bundle will be unaffected.

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, usage_key_str)#

Get metadata about an existing XBlock in the content library

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class openedx.core.djangoapps.content_libraries.views.LibraryBlocksView(**kwargs)#

Bases: APIView

Views to work with XBlocks in a specific content library.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, lib_key_str)#

Get the list of all top-level blocks in this content library

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
post(request, lib_key_str)#

Add a new XBlock to this content library

class openedx.core.djangoapps.content_libraries.views.LibraryCommitView(**kwargs)#

Bases: APIView

Commit/publish or revert all of the draft changes made to the library.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, lib_key_str)#

Revert the draft changes made to the specified block and its descendants. Restore it to the last published version

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
post(request, lib_key_str)#

Commit the draft changes made to the specified block and its descendants.

class openedx.core.djangoapps.content_libraries.views.LibraryDetailsView(**kwargs)#

Bases: APIView

Views to work with a specific content library

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, lib_key_str)#

Delete a content library

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, lib_key_str)#

Get a specific content library

patch(request, lib_key_str)#

Update a content library

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class openedx.core.djangoapps.content_libraries.views.LibraryImportTaskViewSet(**kwargs)#

Bases: ViewSet

Import blocks from Courseware through modulestore.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
basename = None#
create(request, lib_key_str)#

Create and queue an import tasks for this library.

description = None#
detail = None#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

list(request, lib_key_str)#

List all import tasks for this library.

name = None#
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
retrieve(request, lib_key_str, pk=None)#

Retrieve a import task for inspection.

suffix = None#
class openedx.core.djangoapps.content_libraries.views.LibraryRootView(**kwargs)#

Bases: APIView

Views to list, search for, and create content libraries.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request)#

Return a list of all content libraries that the user has permission to view.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
post(request)#

Create a new content library.

class openedx.core.djangoapps.content_libraries.views.LibraryTeamGroupView(**kwargs)#

Bases: APIView

View to add/remove/edit a group’s permissions for a content library.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, lib_key_str, username)#

Remove the specified user’s permission to access or edit this content library.

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
put(request, lib_key_str, group_name)#

Add a group to this content library, with permissions specified in the request body.

class openedx.core.djangoapps.content_libraries.views.LibraryTeamUserView(**kwargs)#

Bases: APIView

View to add/remove/edit an individual user’s permissions for a content library.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
delete(request, lib_key_str, username)#

Remove the specified user’s permission to access or edit this content library.

dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, lib_key_str, username)#

Gets the current permissions settings for a particular user.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
put(request, lib_key_str, username)#

Add a user to this content library, with permissions specified in the request body.

class openedx.core.djangoapps.content_libraries.views.LibraryTeamView(**kwargs)#

Bases: APIView

View to get the list of users/groups who can access and edit the content library.

Note also the ‘allow_public_’ settings which can be edited by PATCHing the library itself (LibraryDetailsView.patch).

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthenticationAllowInactiveUser'>, <class 'edx_rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser'>)#
dispatch(request, *args, **kwargs)#

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

get(request, lib_key_str)#

Get the list of users and groups who have permissions to view and edit this library.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
post(request, lib_key_str)#

Add a user to this content library via email, with permissions specified in the request body.

class openedx.core.djangoapps.content_libraries.views.LtiToolJwksView(**kwargs)#

Bases: LtiToolView

JSON Web Key Sets view.

dispatch(request, *args, **kwargs)#
get(request)#

Return the JWKS.

class openedx.core.djangoapps.content_libraries.views.LtiToolLaunchView(**kwargs)#

Bases: TemplateResponseMixin, LtiToolView

LTI platform tool launch view.

The launch view supports resource link launches and AGS, when enabled by the LTI platform. Other features and resouces are ignored.

dispatch(request, *args, **kwargs)#
get_context_data()#

Setup the template context data.

get_launch_message()#

Return the LTI 1.3 launch message object for the current request.

handle_ags()#

Handle AGS-enabled launches for block in the request.

property launch_data#
post(request)#

Process LTI platform launch requests.

template_name = 'content_libraries/xblock_iframe.html'#
class openedx.core.djangoapps.content_libraries.views.LtiToolLoginView(**kwargs)#

Bases: LtiToolView

Third-party Initiated Login view.

The LTI platform will start the OpenID Connect flow by redirecting the User Agent (UA) to this view. The redirect may be a form POST or a GET. On success the view should redirect the UA to the LTI platform’s authentication URL.

LAUNCH_URI_PARAMETER = 'target_link_uri'#
dispatch(request, *args, **kwargs)#
get(request)#
post(request)#

Initialize 3rd-party login requests to redirect.

class openedx.core.djangoapps.content_libraries.views.LtiToolView(**kwargs)#

Bases: View

Base LTI View initializing common attributes.

dispatch(request, *args, **kwargs)#
setup(request, *args, **kwds)#

Initialize attributes shared by all LTI views.

openedx.core.djangoapps.content_libraries.views.convert_exceptions(fn)#

Catch any Content Library API exceptions that occur and convert them to DRF exceptions so DRF will return an appropriate HTTP response

openedx.core.djangoapps.content_libraries.views.requires_lti_enabled(view_func)#

Modify the view function to raise 404 if content librarie LTI tool was not enabled.

Module contents#