learning_credentials package

Contents

learning_credentials package#

Subpackages#

Submodules#

learning_credentials.admin module#

Admin page configuration for the learning-credentials app.

class learning_credentials.admin.CredentialAdmin(model, admin_site)#

Bases: DjangoObjectActions, ModelAdmin

change_actions = ('reissue_credential',)#
formfield_for_dbfield(db_field, request, **kwargs)#

Assume HTTPS for scheme-less domains pasted into URLFields.

This method can be removed when support for Django versions below 5.0 is dropped.

get_change_actions(request: HttpRequest, object_id: str, form_url: str) list[str]#

Hide the reissue button when the credential is already invalidated.

get_form(request: HttpRequest, obj: Credential | None = None, **kwargs) forms.ModelForm#

Hide the download_url field.

has_add_permission(_request: HttpRequest) bool#

Hide the “Add” button in the admin interface.

has_delete_permission(_request: HttpRequest, _obj: Credential | None = None) bool#

Hide the “Delete” button in the admin interface.

list_display = ('user', 'user_full_name', 'configuration', 'status', 'url', 'created', 'modified')#
list_filter = ('configuration__learning_context_key', 'configuration__credential_type', 'status')#
property media#
readonly_fields = ('uuid', 'verify_uuid', 'user', 'configuration', 'created', 'modified', 'user_full_name', 'learning_context_name', 'status', 'url', 'legacy_id', 'generation_task_id')#
reissue_credential(request: HttpRequest, obj: Credential)#

Reissue the credential for the user.

search_fields = ('configuration__learning_context_key', 'user_full_name', 'user__username', 'user__email', 'uuid', 'verify_uuid')#
url(obj: Credential) str#

Display the download URL as a clickable link.

class learning_credentials.admin.CredentialAssetAdmin(model, admin_site)#

Bases: ModelAdmin

list_display = ('description', 'asset_slug')#
property media#
prepopulated_fields = {'asset_slug': ('description',)}#
class learning_credentials.admin.CredentialConfigurationAdmin(model, admin_site)#

Bases: DjangoObjectActions, ReverseModelAdmin

Admin page for the context-specific credential configuration for each credential type.

It manages the associations between configuration and its corresponding periodic task. The reverse inline provides a way to manage the periodic task from the configuration page.

change_actions = ('generate_credentials',)#
enabled(obj: CredentialConfiguration) bool#

Return the ‘enabled’ status of the periodic task.

form#

alias of CredentialConfigurationForm

generate_credentials(_request: HttpRequest, obj: CredentialConfiguration)#

Custom action to generate credential for the current CredentialConfiguration instance.

Parameters:
  • _request – The request object.

  • obj – The CredentialConfiguration instance.

get_inline_instances(request: HttpRequest, obj: CredentialConfiguration = None) list[admin.ModelAdmin]#

Hide inlines on the “Add” view in Django admin, and show them on the “Change” view.

It differentiates “add” and change “view” based on the requested path because the obj parameter can be None in the “Change” view when rendering the inlines.

Parameters:
  • request – HttpRequest object

  • obj – The object being changed, None for add view

Returns:

A list of InlineModelAdmin instances to be rendered for add/changing an object

get_readonly_fields(_request: HttpRequest, obj: CredentialConfiguration = None) tuple#

Make the learning_context_key field read-only.

inline_reverse = [('periodic_task', {'fields': ['enabled', 'interval', 'crontab', 'clocked', 'start_time', 'expires', 'one_off']})]#
inline_type = 'stacked'#
interval(obj: CredentialConfiguration) IntervalSchedule#

Return the interval of the credentialedential generation task.

list_display = ('learning_context_key', 'credential_type', 'enabled', 'interval')#
list_filter = ('learning_context_key', 'credential_type', 'periodic_task__enabled')#
property media#
search_fields = ('learning_context_key', 'credential_type__name')#
class learning_credentials.admin.CredentialConfigurationForm(*args, **kwargs)#

Bases: ModelForm, DocstringOptionsMixin

class Meta#

Bases: object

fields = ('learning_context_key', 'credential_type', 'custom_options')#
model#

alias of CredentialConfiguration

base_fields = {'credential_type': <django.forms.models.ModelChoiceField object>, 'custom_options': <jsonfield.forms.JSONField object>, 'learning_context_key': <django.forms.fields.CharField object>}#
clean_learning_context_key() str#

Validate the learning_context_key field to ensure it is a valid CourseKey or LearningPathKey.

declared_fields = {}#
property media#

Return all media required to render the widgets on this form.

class learning_credentials.admin.CredentialTypeAdmin(model, admin_site)#

Bases: ModelAdmin

form#

alias of CredentialTypeAdminForm

list_display = ('name', 'retrieval_func', 'generation_func')#
property media#
class learning_credentials.admin.CredentialTypeAdminForm(*args, **kwargs)#

Bases: ModelForm, DocstringOptionsMixin

Generate a list of available functions for the function fields.

class Meta#

Bases: object

fields = '__all__'#
model#

alias of CredentialType

base_fields = {'custom_options': <jsonfield.forms.JSONField object>, 'generation_func': <django.forms.fields.ChoiceField object>, 'name': <django.forms.fields.CharField object>, 'retrieval_func': <django.forms.fields.ChoiceField object>}#
declared_fields = {'generation_func': <django.forms.fields.ChoiceField object>, 'retrieval_func': <django.forms.fields.ChoiceField object>}#
property media#

Return all media required to render the widgets on this form.

class learning_credentials.admin.DocstringOptionsMixin#

Bases: object

A mixin to add the docstring of the function to the help text of the function field.

learning_credentials.apps module#

learning_credentials Django application initialization.

class learning_credentials.apps.LearningCredentialsConfig(app_name, app_module)#

Bases: AppConfig

Configuration for the learning_credentials Django application.

name = 'learning_credentials'#
plugin_app: ClassVar[dict[str, dict[str, dict]]] = {'settings_config': {'lms.djangoapp': {'common': {'relative_path': 'settings.common'}, 'production': {'relative_path': 'settings.production'}}}, 'url_config': {'lms.djangoapp': {'app_name': 'learning_credentials', 'namespace': 'learning_credentials'}}}#
verbose_name = 'Learning Credentials'#

learning_credentials.compat module#

Proxies and compatibility code for edx-platform features.

This module moderates access to all edx-platform features allowing for cross-version compatibility code. It also simplifies running tests outside edx-platform’s environment by stubbing these functions in unit tests.

learning_credentials.compat.get_celery_app() Celery#

Get Celery app to reuse configuration and queues.

learning_credentials.compat.get_course_enrollments(course_id: CourseKey, user_id: int | None = None) list[User]#

Get the course enrollments from Open edX.

learning_credentials.compat.get_course_grade(user: User, course_id: CourseKey)#

Get the CourseGrade instance from Open edX.

learning_credentials.compat.get_course_grading_policy(course_id: CourseKey) dict#

Get the course grading policy from Open edX.

learning_credentials.compat.get_default_storage_url() str#

Get the default storage URL from Open edX.

learning_credentials.compat.get_learning_context_name(learning_context_key: LearningContextKey) str#

Get the learning context (course or Learning Path) name.

learning_credentials.compat.get_localized_credential_date(date: datetime) str#

Get the localized date from Open edX.

Parameters:

date – The datetime to format.

Returns:

The formatted date string.

learning_credentials.compat.prefetch_course_grades(course_id: CourseKey, users: list[User])#

Prefetch the course grades from Open edX.

This optimizes retrieving grades for multiple users.

learning_credentials.exceptions module#

Custom exceptions for the learning-credentials app.

exception learning_credentials.exceptions.AssetNotFoundError#

Bases: Exception

Raised when the asset_slug is not found in the CredentialAsset model.

exception learning_credentials.exceptions.CredentialGenerationError#

Bases: Exception

Raised when the credential generation Celery task fails.

learning_credentials.generators module#

This module provides functions to generate credentials.

The functions prefixed with generate_ are automatically detected by the admin page and are used to generate the credentials for the users.

We will move this module to an external repository (a plugin).

learning_credentials.generators.generate_pdf_credential(credential: Credential, options: dict[str, Any], *, invalidate: bool = False) str#

Generate or invalidate a PDF credential.

Parameters:
  • credential – The Credential instance to generate or invalidate the PDF for.

  • options – The custom options for the credential.

  • invalidate – If True, invalidates the credential instead of generating it. The PDF is moved to an archive location and made inaccessible.

Returns:

The URL of the saved credential, or empty string if invalidated.

Options:

  • template (required): The slug of the PDF template asset.

  • template_multiline: Alternative template for multiline context names (when using ‘n’).

  • defaults: Global defaults for all text elements.
    • font: Font name (asset slug). Default: Helvetica.

    • color: Hex color code. Default: #000.

    • size: Font size in points. Default: 12.

    • char_space: Character spacing. Default: 0.

    • uppercase: Convert text to uppercase. Default: false.

    • line_height: Line height multiplier for multiline text. Default: 1.1.

  • text_elements: Configuration for text elements. Standard elements (name, context, date) have

    defaults and render automatically. Set to false to hide. Custom elements require ‘text’ and ‘y’ properties. Element properties: - text: Text content with {placeholder} substitution. Available: {name}, {context_name}, {issue_date}. - y: Vertical position (PDF coordinates from bottom). - size: Font size (inherited from defaults.size). - font: Font name (inherited from defaults.font). - color: Hex color (inherited from defaults.color). - char_space: Character spacing (inherited from defaults.char_space). - uppercase: Convert text to uppercase (inherited from defaults.uppercase). - line_height: Line height multiplier for multiline text (inherited from defaults.line_height).

Example:

{
  "template": "certificate-template",
  "defaults": {"font": "CustomFont", "color": "#333"},
  "text_elements": {
    "name": {"y": 300, "uppercase": true},
    "context": {"text": "Custom Course Name"},
    "date": false,
    "award_line": {"text": "Awarded on {issue_date}", "y": 140, "size": 14}
  }
}

learning_credentials.models module#

Database models for learning_credentials.

class learning_credentials.models.Credential(*args, **kwargs)#

Bases: TimeStampedModel

Model to represent each credential awarded to a user for a course.

This model contains information about the related course, the user who earned the credential, the download URL for the credential PDF, and the associated credential generation task.

Note

Credentials are identified by UUIDs rather than integer keys to prevent enumeration attacks or privacy leaks.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

class Status(value)#

Bases: TextChoices

Status of the credential generation task.

AVAILABLE = 'available'#
ERROR = 'error'#
GENERATING = 'generating'#
INVALIDATED = 'invalidated'#
configuration#

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.

configuration_id#
created#

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

credential_type#

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

download_url#

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

generation_task_id#

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(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=False, **kwargs)#
get_status_display(*, field=<django.db.models.fields.CharField: status>)#
invalidated_at#

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

invalidation_reason#

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

learning_context_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.

learning_context_name#

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

legacy_id#

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

modified#

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

objects = <django.db.models.manager.Manager object>#
reissue() Self#

Invalidate the current credential and create a new one.

save(*args, **kwargs)#

If the invalidation reason is set, trigger the invalidation and update the timestamp.

send_email()#

Send a credential link to the student.

status#

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

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_full_name#

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

user_id#
uuid#

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

verify_uuid#

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

class learning_credentials.models.CredentialAsset(*args, **kwargs)#

Bases: TimeStampedModel

A set of assets to be used in custom credential templates.

This model stores assets used during credential generation process, such as PDF templates, images, fonts.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

asset#

The descriptor for the file attribute on the model instance. Return a FieldFile when accessed so you can write code like:

>>> from myapp.models import MyModel
>>> instance = MyModel.objects.get(pk=1)
>>> instance.file.size

Assign a file object on assignment so you can do:

>>> with open('/path/to/hello.world') as f:
...     instance.file = File(f)
asset_slug#

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

created#

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

description#

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

classmethod get_asset_by_slug(asset_slug: str) File#

Fetch a credential template asset by its slug from the database.

Parameters:

asset_slug – The slug of the asset to be retrieved.

Returns:

The file associated with the asset slug.

Raises:

AssetNotFound – If no asset exists with the provided slug in the CredentialAsset database model.

get_next_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, 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.

modified#

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

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

If the object is being created, save the asset first, then save the object.

template_assets_path(filename: str) str#

Delete the file if it already exists and returns the credential template asset file path.

Parameters:

filename – File to upload.

Return path:

Path of asset file e.g. credential_template_assets/1/filename.

class learning_credentials.models.CredentialConfiguration(*args, **kwargs)#

Bases: TimeStampedModel

Model to store context-specific credential configurations for each credential type.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

created#

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

credential_set#

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.

credential_type#

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.

credential_type_id#
custom_options#

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

filter_out_user_ids_with_credentials(user_ids: list[int]) list[int]#

Filter out user IDs that already have a credential for this course and credential type.

Parameters:

user_ids – A list of user IDs to filter.

Returns:

A list of user IDs that either: 1. Do not have a credential for this course and credential type. 2. Have such a credential with an error status.

generate_credential_for_user(user_id: int, celery_task_id: int = 0) Credential#

Celery task for processing a single user’s credential.

This function retrieves an CredentialConfiguration object based on context ID and credential type, retrieves the data using the retrieval_func specified in the associated CredentialType object, and passes this data to the function specified in the generation_func field.

Parameters:
  • user_id – The ID of the user to process the credential for.

  • celery_task_id (optional) – The ID of the Celery task that is running this function.

Returns:

The generated Credential object.

generate_credentials()#

This method allows manual credential generation from the Django admin.

get_eligible_user_ids(user_id: int | None = None) list[int]#

Get the list of eligible learners for the given learning context.

Parameters:

user_id – Optional. If provided, only check eligibility for this user.

Returns:

A list of eligible user IDs.

classmethod get_enabled_configurations() QuerySet[Self]#

Get the list of enabled configurations.

Returns:

A list of CredentialConfiguration objects.

get_next_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=False, **kwargs)#
get_user_eligibility_details(user_id: int) dict[str, Any]#

Get detailed eligibility information for a specific user.

Parameters:

user_id – The user ID to check eligibility for.

Returns:

Dictionary containing eligibility details and progress information.

id#

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

learning_context_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.

modified#

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

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

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.

periodic_task_id#
save(*args, **kwargs)#

Create a new PeriodicTask every time a new CredentialConfiguration is created.

class learning_credentials.models.CredentialType(*args, **kwargs)#

Bases: TimeStampedModel

Model to store global credential configurations for each type.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

clean()#

Ensure that the retrieval_func and generation_func exist.

created#

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

credentialconfiguration_set#

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.

custom_options#

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

generation_func#

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(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, 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.

modified#

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

name#

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

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

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

learning_credentials.models.post_delete_periodic_task(sender, instance, *_args, **_kwargs)#

Delete the associated periodic task when the object is deleted.

learning_credentials.processors module#

This module contains processors for credential criteria.

The functions prefixed with retrieve_ are automatically detected by the admin page and are used to compute per-user progress for the credential type, following the contract described below.

All processors return dict[int, dict[str, Any]] — a mapping from user ID to detailed progress info for all relevant users, including those who are not eligible. Each user’s dict always includes an is_eligible boolean.

We will move this module to an external repository (a plugin).

learning_credentials.processors.retrieve_completions(learning_context_key: LearningContextKey, options: dict[str, Any], user_id: int | None = None) dict[int, dict[str, Any]]#

Retrieve detailed completion progress for users through the Completion Aggregator API.

Parameters:
  • learning_context_key – The learning context key (course or learning path).

  • options – The custom options for the credential.

  • user_id – Optional. If provided, only process this specific user.

Returns:

A dict mapping user IDs to their completion progress (is_eligible, current_completion, required_completion).

Options:
  • required_completion: The minimum required completion percentage. The default value is 0.9.

  • steps: For learning paths only. A dictionary with step-specific options in the format {”&lt;course_key&gt;”: {…}}. If provided, each course in the learning path will use its specific options instead of the global options. Example:

    {
      "required_completion": 0.8,
      "steps": {
        "course-v1:edX+DemoX+Demo_Course": {
          "required_completion": 0.9
        },
        "course-v1:edX+CS101+2023": {
          "required_completion": 0.7
        }
      }
    }
    
learning_credentials.processors.retrieve_completions_and_grades(learning_context_key: LearningContextKey, options: dict[str, Any], user_id: int | None = None) dict[int, dict[str, Any]]#

Retrieve detailed progress for users that must meet both completion and grade criteria.

This processor combines the functionality of retrieve_completions and retrieve_subsection_grades. To be eligible, learners must satisfy both sets of criteria.

Parameters:
  • learning_context_key – The learning context key (course or learning path).

  • options – The custom options for the credential.

  • user_id – Optional. If provided, only process this specific user.

Returns:

A dict mapping user IDs to their combined progress.

Options:
  • required_completion: The minimum required completion percentage (default: 0.9)

  • required_grades: A dictionary of required grades for each category, where the keys are the category names and the values are the minimum required grades. The grades are percentages in the range [0, 1]. Example:

    {
      "required_grades": {
        "Homework": 0.4,
        "Exam": 0.9,
        "Total": 0.8
      }
    }
    
  • steps: For learning paths only. A dictionary with step-specific options in the format {”&lt;course_key&gt;”: {…}}. If provided, each course in the learning path will use its specific options instead of the global options. Example:

    {
      "required_completion": 0.8,
      "required_grades": {
        "Total": 0.7
      },
      "steps": {
        "course-v1:edX+DemoX+Demo_Course": {
          "required_completion": 0.9,
          "required_grades": {
            "Total": 0.8
          }
        },
        "course-v1:edX+CS101+2023": {
          "required_completion": 0.7,
          "required_grades": {
            "Homework": 0.5,
            "Total": 0.6
          }
        }
      }
    }
    
learning_credentials.processors.retrieve_subsection_grades(learning_context_key: LearningContextKey, options: dict[str, Any], user_id: int | None = None) dict[int, dict[str, Any]]#

Retrieve detailed grade progress for users in a learning context.

Parameters:
  • learning_context_key – The learning context key (course or learning path).

  • options – The custom options for the credential.

  • user_id – Optional. If provided, only process this specific user.

Returns:

A dict mapping user IDs to their grade progress (is_eligible, current_grades, required_grades).

Options:
  • required_grades: A dictionary of required grades for each category, where the keys are the category names and the values are the minimum required grades. The grades are percentages, so they should be in the range [0, 1]. See the following example:

    {
      "required_grades": {
        "Homework": 0.4,
        "Exam": 0.9,
        "Total": 0.8
      }
    }
    

    It means that the user must receive at least 40% in the Homework category and 90% in the Exam category. The “Total” key is a special value used to specify the minimum required grade for all categories in the course. Let’s assume that we have the following grading policy (the percentages are the weights of each category): 1. Homework: 20% 2. Lab: 10% 3. Exam: 70% The grades for the Total category will be calculated as follows: total_grade = (homework_grade * 0.2) + (lab_grade * 0.1) + (exam_grade * 0.7)

  • steps: For learning paths only. A dictionary with step-specific options in the format {”&lt;course_key&gt;”: {…}}. If provided, each course in the learning path will use its specific options instead of the global options. Example:

    {
      "required_grades": {
        "Total": 0.8
      },
      "steps": {
        "course-v1:edX+DemoX+Demo_Course": {
          "required_grades": {
            "Total": 0.9
          }
        },
        "course-v1:edX+CS101+2023": {
          "required_grades": {
            "Homework": 0.5,
            "Total": 0.7
          }
        }
      }
    }
    

learning_credentials.tasks module#

Asynchronous Celery tasks.

learning_credentials.urls module#

URLs for learning_credentials.

Module contents#

A pluggable service for preparing Open edX credentials.