openedx.core.djangoapps.content_libraries package

Contents

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

class openedx.core.djangoapps.content_libraries.api.CollectionMetadata(key: str, title: str)#

Bases: object

Class to represent collection metadata in a content library.

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, learning_package: LearningPackage, title='', description='', num_blocks=0, version=0, type='complex', last_published: datetime = None, last_draft_created: datetime = None, last_draft_created_by: datetime = None, published_by='', has_unpublished_changes=False, has_unpublished_deletes=False, allow_lti=False, allow_public_learning=False, allow_public_read=False, license='', created: datetime = None, updated: datetime = None)#

Bases: object

Class that represents the metadata about a content library.

class openedx.core.djangoapps.content_libraries.api.ContentLibraryPermissionEntry(user: AbstractUser = None, group: Group = 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.LibraryCollectionAlreadyExists#

Bases: IntegrityError

A Collection with that key 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, modified: datetime, draft_version_num: int, published_version_num: int = None, display_name='', last_published: datetime = None, last_draft_created: datetime = None, last_draft_created_by='', published_by='', has_unpublished_changes=False, created: datetime = None, collections: list[CollectionMetadata] = NOTHING)#

Bases: object

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

classmethod from_component(library_key, component, associated_collections=None)#

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_path, file_content, user=None) 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_path 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, user_id=None)#

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

openedx.core.djangoapps.content_libraries.api.create_library_collection(library_key: LibraryLocatorV2, collection_key: str, title: str, *, description: str = '', created_by: int | None = None, content_library: ContentLibrary | None = None) Collection#

Creates a Collection in the given ContentLibrary.

If you’ve already fetched a ContentLibrary for the given library_key, pass it in here to avoid refetching.

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_path, user=None)#

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, order=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, include_collections=False) 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: Should this be in the general XBlock API rather than the libraries API?

openedx.core.djangoapps.content_libraries.api.get_library_collection_from_usage_key(collection_usage_key: LibraryCollectionLocator) Collection#

Return a Collection using the LibraryCollectionLocator

openedx.core.djangoapps.content_libraries.api.get_library_collection_usage_key(library_key: LibraryLocatorV2, collection_key: str) LibraryCollectionLocator#

Returns the LibraryCollectionLocator associated to a collection

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.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.import_staged_content_from_user_clipboard(library_key: LibraryLocatorV2, user, block_id) XBlock#

Create a new library block and populate it with staged content from clipboard

Returns the newly created library block

openedx.core.djangoapps.content_libraries.api.library_component_usage_key(library_key: LibraryLocatorV2, component: Component) LibraryUsageLocatorV2#

Returns a LibraryUsageLocatorV2 for the given library + component.

openedx.core.djangoapps.content_libraries.api.publish_changes(library_key, user_id=None)#

Publish all pending changes to the specified library.

openedx.core.djangoapps.content_libraries.api.publish_component_changes(usage_key: LibraryUsageLocatorV2, user)#

Publish all pending changes in a single component.

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

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) ComponentVersion#

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.

Returns the version number of the newly created ComponentVersion.

openedx.core.djangoapps.content_libraries.api.set_library_component_collections(library_key: LibraryLocatorV2, component: Component, *, collection_keys: list[str], created_by: int | None = None, content_library: ContentLibrary | None = None) Component#

It Associates the component with collections for the given collection keys.

Only collections in queryset are associated with component, all previous component-collections associations are removed.

If you’ve already fetched the ContentLibrary, pass it in to avoid refetching.

Raises: * ContentLibraryCollectionNotFound if any of the given collection_keys don’t match Collections in the given library.

Returns the updated Component.

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.api.update_library_collection(library_key: LibraryLocatorV2, collection_key: str, *, title: str | None = None, description: str | None = None, content_library: ContentLibrary | None = None) Collection#

Updates a Collection in the given ContentLibrary.

openedx.core.djangoapps.content_libraries.api.update_library_collection_components(library_key: LibraryLocatorV2, collection_key: str, *, usage_keys: list[UsageKeyV2], created_by: int | None = None, remove=False, content_library: ContentLibrary | None = None) Collection#

Associates the Collection with Components for the given UsageKeys.

By default the Components are added to the Collection. If remove=True, the Components are removed from the Collection.

If you’ve already fetched the ContentLibrary, pass it in to avoid refetching.

Raises: * ContentLibraryCollectionNotFound if no Collection with the given pk is found in the given library. * ContentLibraryBlockNotFound if any of the given usage_keys don’t match Components in the given library.

Returns the updated Collection.

openedx.core.djangoapps.content_libraries.api.user_can_create_library(user: AbstractUser) bool#

Check if the user has permission to create a content library.

openedx.core.djangoapps.content_libraries.api.validate_can_add_block_to_library(library_key: LibraryLocatorV2, block_type: str, block_id: str) tuple[ContentLibrary, LibraryUsageLocatorV2]#

Perform checks to validate whether a new block with block_id and type block_type can be added to the library with key library_key.

Returns the ContentLibrary that has the passed in library_key and newly created LibraryUsageLocatorV2 if validation successful, otherwise raises errors.

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 (Learning-Core-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 Learning Core, not the old content libraries based on modulestore.

block_exists(usage_key: LibraryUsageLocatorV2)#

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: User | AnonymousUser, usage_key: UsageKeyV2) bool#

Assuming a block with the specified ID (usage_key) exists, does the specified user have permission to edit it (make changes to the fields / authored data store)?

May raise ContentLibraryNotFound if the library does not exist.

can_view_block(user: User | AnonymousUser, usage_key: UsageKeyV2) bool#

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.)?

May raise ContentLibraryNotFound if the library does not exist.

can_view_block_for_editing(user: User | AnonymousUser, usage_key: UsageKeyV2) bool#

Assuming a block with the specified ID (usage_key) exists, does the specified user have permission to view its fields and OLX details (but not necessarily to make changes to it)?

May raise ContentLibraryNotFound if the library does not exist.

send_block_updated_event(usage_key: UsageKeyV2)#

Send a “block updated” event for the library block with the given usage_key.

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 learning-core-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 (learning core). 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 Learning Core, 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 Learning Core. 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, Learning-Core-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.CollectionMetadataSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for CollectionMetadata

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.ContentLibraryCollectionComponentsUpdateSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for adding/removing Components to/from a Collection.

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

Bases: ModelSerializer

Serializer for a Content Library Collection

class Meta#

Bases: object

fields = '__all__'#
model#

alias of Collection

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

Bases: Serializer

Serializer for updating a Collection in a Content Library

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

Bases: Serializer

Serializer for adding/removing Collections to/from a Component.

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

get_can_edit_library(obj)#

Verifies if the user in request has permission to edit a library.

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.LibraryPasteClipboardSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for pasting clipboard data into 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)

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

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

Bases: Serializer

Serializes a UsageKeyV2.

to_internal_value(value: str) UsageKeyV2#

Returns a UsageKeyV2 from the string value.

Raises ValidationError if invalid UsageKeyV2.

to_representation(value: UsageKeyV2) str#

Returns the UsageKeyV2 value as a string.

openedx.core.djangoapps.content_libraries.signal_handlers module#

Content library signal handlers.

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

Raises LIBRARY_COLLECTION_DELETED for the deleted Collection.

openedx.core.djangoapps.content_libraries.signal_handlers.library_collection_entities_changed(sender, instance, action, pk_set, **kwargs)#

Sends a CONTENT_OBJECT_ASSOCIATIONS_CHANGED event for components added/removed/cleared from a collection.

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

Sends a CONTENT_OBJECT_ASSOCIATIONS_CHANGED event for components removed from a collection.

openedx.core.djangoapps.content_libraries.signal_handlers.library_collection_entity_saved(sender, instance, created, **kwargs)#

Sends a CONTENT_OBJECT_ASSOCIATIONS_CHANGED event for components added to a collection.

openedx.core.djangoapps.content_libraries.signal_handlers.library_collection_saved(sender, instance, created, **kwargs)#

Raises LIBRARY_COLLECTION_CREATED if the Collection is new, or LIBRARY_COLLECTION_UPDATED if updated an existing Collection.

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 learning core. 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 learning core 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#

openedx.core.djangoapps.content_libraries.views module#

openedx.core.djangoapps.content_libraries.views_collections module#

Module contents#