lms.djangoapps.discussion.rest_api package#

Submodules#

lms.djangoapps.discussion.rest_api.api module#

Discussion API internal interface

class lms.djangoapps.discussion.rest_api.api.DiscussionEntity(value)#

Bases: Enum

Enum for different types of discussion related entities

comment = 'comment'#
thread = 'thread'#
class lms.djangoapps.discussion.rest_api.api.DiscussionTopic(topic_id: str | None, name: str, thread_list_url: str, children: List[DiscussionTopic] | None = None, thread_counts: Dict[str, int] | None = None)#

Bases: object

Class for discussion topic structure

lms.djangoapps.discussion.rest_api.api.add_stats_for_users_with_null_values(course_stats, users_in_course)#

Update users stats for users with no discussion stats available in course

lms.djangoapps.discussion.rest_api.api.create_comment(request, comment_data)#

Create a comment.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • comment_data – The data for the created comment.

Returns:

The created comment; see discussion.rest_api.views.CommentViewSet for more detail.

lms.djangoapps.discussion.rest_api.api.create_thread(request, thread_data)#

Create a thread.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • thread_data – The data for the created thread.

Returns:

The created thread; see discussion.rest_api.views.ThreadViewSet for more detail.

lms.djangoapps.discussion.rest_api.api.delete_comment(request, comment_id)#

Delete a comment.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • comment_id – The id of the comment to delete

Raises:

PermissionDenied – if user does not have permission to delete thread

lms.djangoapps.discussion.rest_api.api.delete_thread(request, thread_id)#

Delete a thread.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • thread_id – The id for the thread to delete

Raises:

PermissionDenied – if user does not have permission to delete thread

lms.djangoapps.discussion.rest_api.api.get_comment_list(request, thread_id, endorsed, page, page_size, flagged=False, requested_fields=None)#

Return the list of comments in the given thread.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • thread_id – The id of the thread to get comments for.

  • endorsed – Boolean indicating whether to get endorsed or non-endorsed comments (or None for all comments). Must be None for a discussion thread and non-None for a question thread.

  • page – The page number (1-indexed) to retrieve

  • page_size – The number of comments to retrieve per page

  • flagged – Filter comments by flagged for abuse status.

  • requested_fields – Indicates which additional fields to return for

  • comment. (each) –

Returns:

A paginated result containing a list of comments; see discussion.rest_api.views.CommentViewSet for more detail.

lms.djangoapps.discussion.rest_api.api.get_course(request, course_key)#

Return general discussion information for the course.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • course_key – The key of the course to get information for

Returns:

The course information; see discussion.rest_api.views.CourseView for more detail.

Raises:
  • CourseNotFoundError – if the course does not exist or is not accessible

  • to the requesting user

lms.djangoapps.discussion.rest_api.api.get_course_discussion_user_stats(request, course_key_str: str, page: int, page_size: int, order_by: UserOrdering = None, username_search_string: str = None) Dict#

Get paginated course discussion stats for users in the course.

Parameters:
  • request (Request) – DRF request

  • course_key_str (str) – course key string

  • page (int) – Page number to fetch

  • page_size (int) – Number of items in each page

  • order_by (UserOrdering) – The ordering to use for the user stats

  • username_search_string (str) – Partial string to match user names

Returns:

Paginated data of a user’s discussion stats sorted based on the specified ordering.

lms.djangoapps.discussion.rest_api.api.get_course_topics(request: Request, course_key: CourseKey, topic_ids: Set[str] | None = None)#

Returns the course topic listing for the given course and user; filtered by ‘topic_ids’ list if given.

Parameters:
  • course_key – The key of the course to get topics for

  • topic_ids – A list of topic IDs for which topic details are requested

Returns:

A course topic listing dictionary; see discussion.rest_api.views.CourseTopicViews for more detail.

Raises:

DiscussionNotFoundError – If topic/s not found for given topic_ids.

lms.djangoapps.discussion.rest_api.api.get_course_topics_v2(course_key: CourseKey, user: User, topic_ids: Iterable[str] | None = None, order_by: TopicOrdering = TopicOrdering.COURSE_STRUCTURE) List[Dict]#

Returns the course topic listing for the given course and user; filtered by ‘topic_ids’ list if given.

Parameters:
  • course_key – The key of the course to get topics for

  • user – The requesting user, for access control

  • topic_ids – A list of topic IDs for which topic details are requested

  • order_by – The sort ordering for the returned list of topics

Returns:

A list of discussion topics for the course.

Raises:

ValidationError – If unsupported ordering is used.

lms.djangoapps.discussion.rest_api.api.get_courseware_topics(request: Request, course_key: CourseKey, course: CourseBlock, topic_ids: List[str] | None, thread_counts: Dict[str, Dict[str, int]]) Tuple[List[Dict], Set[str]]#

Returns a list of topic trees for courseware-linked topics.

Parameters:
  • request – The django request objects used for build_absolute_uri.

  • course_key – The key of the course to get discussion threads for.

  • course – The course for which topics are requested.

  • topic_ids – A list of topic IDs for which details are requested. This is optional. If None then all course topics are returned.

  • thread_counts – A map of the thread ids to the count of each type of thread in them e.g. discussion, question

Returns:

A list of courseware topics and a set of existing topics among topic_ids.

lms.djangoapps.discussion.rest_api.api.get_learner_active_thread_list(request, course_key, query_params)#

Returns a list of active threads for a particular user

Parameters:

request: The django request objects used for build_absolute_uri course_key: The key of the course query_params: Parameters to fetch data from comments service. It must contain

user_id, course_id, page, per_page, group_id, count_flagged

Returns:

A paginated result containing a list of threads.

** Sample Response {

“results”: [
{

“id”: “thread_id”, “author”: “author_username”, “author_label”: “Staff”, “created_at”: “2010-01-01T12:00:00Z”, “updated_at”: “2010-01-01T12:00:00Z”, “raw_body”: “<p></p>”, “rendered_body”: “<p></p>”, “abuse_flagged”: false, “voted”: false, “vote_count”: 0, “editable_fields”: [

“abuse_flagged”, “anonymous”, “close_reason_code”, “closed”, “edit_reason_code”, “following”, “pinned”, “raw_body”, “read”, “title”, “topic_id”, “type”, “voted”

], “can_delete”: true, “anonymous”: false, “anonymous_to_peers”: false, “last_edit”: {

“original_body”: “<p></p>”, “reason_code”: null, “editor_username”: “author_username”, “created_at”: “2010-01-01T12:00:00Z”

}, “course_id”: “course-v1:edX+DemoX+Demo_Course”, “topic_id”: “i4x-edx-eiorguegnru-course-foobarbaz”, “group_id”: null, “group_name”: null, “type”: “discussion”, “preview_body”: “”, “abuse_flagged_count”: null, “title”: “Post Title”, “pinned”: false, “closed”: false, “following”: false, “comment_count”: 1, “unread_comment_count”: 0, “comment_list_url”: “http://localhost:18000/api/discussion/v1/comments/?thread_id=thread_id”, “endorsed_comment_list_url”: null, “non_endorsed_comment_list_url”: null, “read”: true, “has_endorsed”: false, “close_reason”: null, “closed_by”: null, “users”: {

“username”: {
“profile”: {
“image”: {

“has_image”: false, “image_url_full”: “http://localhost:18000/static/images/profiles/default_500.png”, “image_url_large”: “http://localhost:18000/static/images/profiles/default_120.png”, “image_url_medium”: “http://localhost:18000/static/images/profiles/default_50.png”, “image_url_small”: “http://localhost:18000/static/images/profiles/default_30.png

}

}

}

}

], “pagination”: {

“next”: None, “previous”: None, “count”: 10, “num_pages”: 1

}

}

lms.djangoapps.discussion.rest_api.api.get_non_courseware_topics(request: Request, course_key: CourseKey, course: CourseBlock, topic_ids: List[str] | None, thread_counts: Dict[str, Dict[str, int]]) Tuple[List[Dict], Set[str]]#

Returns a list of topic trees that are not linked to courseware.

Parameters:
  • request – The django request objects used for build_absolute_uri.

  • course_key – The key of the course to get discussion threads for.

  • course – The course for which topics are requested.

  • topic_ids – A list of topic IDs for which details are requested. This is optional. If None then all course topics are returned.

  • thread_counts – A map of the thread ids to the count of each type of thread in them e.g. discussion, question

Returns:

A list of non-courseware topics and a set of existing topics among topic_ids.

lms.djangoapps.discussion.rest_api.api.get_response_comments(request, comment_id, page, page_size, requested_fields=None)#

Return the list of comments for the given thread response.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • comment_id – The id of the comment/response to get child comments for.

  • page – The page number (1-indexed) to retrieve

  • page_size – The number of comments to retrieve per page

  • requested_fields – Indicates which additional fields to return for

  • comment. (each child) –

Returns:

A paginated result containing a list of comments

lms.djangoapps.discussion.rest_api.api.get_thread(request, thread_id, requested_fields=None, course_id=None)#

Retrieve a thread.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • thread_id – The id for the thread to retrieve

  • course_id – the id of the course the threads belongs to

  • requested_fields – Indicates which additional fields to return for

  • thread. (i.e. ['profile_image']) –

lms.djangoapps.discussion.rest_api.api.get_thread_list(request: Request, course_key: CourseKey, page: int, page_size: int, topic_id_list: List[str] | None = None, text_search: str | None = None, following: bool | None = False, author: str | None = None, thread_type: Literal['discussion', 'question'] | None = None, flagged: bool | None = None, view: Literal['unread', 'unanswered'] | None = None, order_by: Literal['last_activity_at', 'comment_count', 'vote_count'] = 'last_activity_at', order_direction: Literal['desc'] = 'desc', requested_fields: List[Literal['profile_image']] | None = None, count_flagged: bool | None = None)#

Return the list of all discussion threads pertaining to the given course

Parameters:

request: The django request objects used for build_absolute_uri course_key: The key of the course to get discussion threads for page: The page number (1-indexed) to retrieve page_size: The number of threads to retrieve per page count_flagged: If true, fetch the count of flagged items in each thread topic_id_list: The list of topic_ids to get the discussion threads for text_search A text search query string to match following: If true, retrieve only threads the requester is following author: If provided, retrieve only threads by this author thread_type: filter for “discussion” or “question threads flagged: filter for only threads that are flagged view: filters for either “unread” or “unanswered” threads order_by: The key in which to sort the threads by. The only values are

“last_activity_at”, “comment_count”, and “vote_count”. The default is “last_activity_at”.

order_direction: The direction in which to sort the threads by. The default

and only value is “desc”. This will be removed in a future major version.

requested_fields: Indicates which additional fields to return

for each thread. (i.e. [‘profile_image’])

Note that topic_id_list, text_search, and following are mutually exclusive.

Returns:

A paginated result containing a list of threads; see discussion.rest_api.views.ThreadViewSet for more detail.

Raises:

PermissionDenied: If count_flagged is set but the user isn’t privileged ValidationError: if an invalid value is passed for a field. ValueError: if more than one of the mutually exclusive parameters is

provided

CourseNotFoundError: if the requesting user does not have access to the requested course PageNotFoundError: if page requested is beyond the last

lms.djangoapps.discussion.rest_api.api.get_thread_list_url(request, course_key, topic_id_list=None, following=False)#

Returns the URL for the thread_list_url field, given a list of topic_ids

lms.djangoapps.discussion.rest_api.api.get_user_comments(request: Request, author: User, course_key: CourseKey, flagged: bool = False, page: int = 1, page_size: int = 10, requested_fields: List[str] | None = None)#

Returns the list of comments made by the user in the requested course.

Parameters:
  • request – The django request object.

  • author – The user to get comments from.

  • course_key – The course locator to filter the comments.

  • flagged – Filter comments by flagged status.

  • page – The page number (1-indexed) to retrieve

  • page_size – The number of comments to retrieve per page

  • requested_fields – Indicates which additional fields to return for

  • comment. (each child) –

Returns:

A paginated result containing a list of comments.

lms.djangoapps.discussion.rest_api.api.get_users_without_stats(username_search_string, course_key, page_number, page_size, request, is_privileged)#

This return users with no user stats. This function will be deprecated when this ticket DOS-3414 is resolved

lms.djangoapps.discussion.rest_api.api.get_v2_course_topics_as_v1(request: Request, course_key: CourseKey, topic_ids: Iterable[str] | None = None)#

Returns v2 topics in v1 structure

lms.djangoapps.discussion.rest_api.api.get_v2_courseware_topics_as_v1(request, course_key, sequentials, topics)#

Returns v2 courseware topics list as v1 structure

lms.djangoapps.discussion.rest_api.api.get_v2_non_courseware_topics_as_v1(request, course_key, topics)#

Takes v2 topics list and returns v1 list of non courseware topics

lms.djangoapps.discussion.rest_api.api.update_comment(request, comment_id, update_data)#

Update a comment.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • comment_id – The id for the comment to update.

  • update_data – The data to update in the comment.

Returns:

The updated comment; see discussion.rest_api.views.CommentViewSet for more detail.

Raises:
  • CommentNotFoundError – if the comment does not exist or is not accessible

  • to the requesting user

  • PermissionDenied – if the comment is accessible to but not editable by the requesting user

  • ValidationError – if there is an error applying the update (e.g. raw_body is empty or thread_id is included)

lms.djangoapps.discussion.rest_api.api.update_thread(request, thread_id, update_data)#

Update a thread.

Parameters:
  • request – The django request object used for build_absolute_uri and determining the requesting user.

  • thread_id – The id for the thread to update.

  • update_data – The data to update in the thread.

Returns:

The updated thread; see discussion.rest_api.views.ThreadViewSet for more detail.

lms.djangoapps.discussion.rest_api.exceptions module#

Errors used by the Discussion API.

exception lms.djangoapps.discussion.rest_api.exceptions.CommentNotFoundError#

Bases: ObjectDoesNotExist

Comment was not found.

exception lms.djangoapps.discussion.rest_api.exceptions.DiscussionBlackOutException(detail=None, code=None)#

Bases: APIException

Discussions are in blackout period.

default_detail = 'Discussions are in blackout period.'#
status_code = 403#
exception lms.djangoapps.discussion.rest_api.exceptions.DiscussionDisabledError#

Bases: ObjectDoesNotExist

Discussion is disabled.

exception lms.djangoapps.discussion.rest_api.exceptions.ThreadNotFoundError#

Bases: ObjectDoesNotExist

Thread was not found.

lms.djangoapps.discussion.rest_api.forms module#

Discussion API forms

class lms.djangoapps.discussion.rest_api.forms.CommentActionsForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: Form

A form to handle fields in comment creation/update that require separate interactions with the comments service.

base_fields = {'abuse_flagged': <django.forms.fields.BooleanField object>, 'voted': <django.forms.fields.BooleanField object>}#
declared_fields = {'abuse_flagged': <django.forms.fields.BooleanField object>, 'voted': <django.forms.fields.BooleanField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.CommentGetForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: _PaginationForm

A form to validate query parameters in the comment retrieval endpoint

base_fields = {'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>}#
declared_fields = {'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.CommentListGetForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: _PaginationForm

A form to validate query parameters in the comment list retrieval endpoint

base_fields = {'endorsed': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'flagged': <django.forms.fields.BooleanField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'thread_id': <django.forms.fields.CharField object>}#
declared_fields = {'endorsed': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'flagged': <django.forms.fields.BooleanField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'thread_id': <django.forms.fields.CharField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.CourseActivityStatsForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: _PaginationForm

Form for validating course activity stats API query parameters

base_fields = {'order_by': <django.forms.fields.ChoiceField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'username': <django.forms.fields.CharField object>}#
declared_fields = {'order_by': <django.forms.fields.ChoiceField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'username': <django.forms.fields.CharField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.CourseDiscussionRolesForm(*args, **kwargs)#

Bases: CourseDiscussionSettingsForm

A form to validate the fields in the course discussion roles requests.

ROLE_CHOICES = (('Moderator', 'Moderator'), ('Community TA', 'Moderator'), ('Group Moderator', 'Group Moderator'))#
base_fields = {'course_id': <django.forms.fields.CharField object>, 'rolename': <django.forms.fields.ChoiceField object>}#
clean_rolename()#

Validate the ‘rolename’ value.

declared_fields = {'course_id': <django.forms.fields.CharField object>, 'rolename': <django.forms.fields.ChoiceField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.CourseDiscussionSettingsForm(*args, **kwargs)#

Bases: Form

A form to validate the fields in the course discussion settings requests.

base_fields = {'course_id': <django.forms.fields.CharField object>}#
clean_course_id()#

Validate the ‘course_id’ value

declared_fields = {'course_id': <django.forms.fields.CharField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.ThreadActionsForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: Form

A form to handle fields in thread creation/update that require separate interactions with the comments service.

base_fields = {'abuse_flagged': <django.forms.fields.BooleanField object>, 'following': <django.forms.fields.BooleanField object>, 'pinned': <django.forms.fields.BooleanField object>, 'read': <django.forms.fields.BooleanField object>, 'voted': <django.forms.fields.BooleanField object>}#
declared_fields = {'abuse_flagged': <django.forms.fields.BooleanField object>, 'following': <django.forms.fields.BooleanField object>, 'pinned': <django.forms.fields.BooleanField object>, 'read': <django.forms.fields.BooleanField object>, 'voted': <django.forms.fields.BooleanField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.ThreadListGetForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: _PaginationForm

A form to validate query parameters in the thread list retrieval endpoint

EXCLUSIVE_PARAMS = ['topic_id', 'text_search', 'following']#
base_fields = {'author': <django.forms.fields.CharField object>, 'count_flagged': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'course_id': <django.forms.fields.CharField object>, 'flagged': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'following': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'order_by': <django.forms.fields.ChoiceField object>, 'order_direction': <django.forms.fields.ChoiceField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'text_search': <django.forms.fields.CharField object>, 'thread_type': <django.forms.fields.ChoiceField object>, 'topic_id': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'view': <django.forms.fields.ChoiceField object>}#
clean()#

Hook for doing any extra form-wide cleaning after Field.clean() has been called on every field. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field named ‘__all__’.

clean_course_id()#

Validate course_id

clean_following()#

Validate following

clean_order_by()#

Return a default choice

clean_order_direction()#

Return a default choice

declared_fields = {'author': <django.forms.fields.CharField object>, 'count_flagged': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'course_id': <django.forms.fields.CharField object>, 'flagged': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'following': <openedx.core.djangoapps.util.forms.ExtendedNullBooleanField object>, 'order_by': <django.forms.fields.ChoiceField object>, 'order_direction': <django.forms.fields.ChoiceField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'text_search': <django.forms.fields.CharField object>, 'thread_type': <django.forms.fields.ChoiceField object>, 'topic_id': <openedx.core.djangoapps.util.forms.MultiValueField object>, 'view': <django.forms.fields.ChoiceField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.TopicListGetForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: Form

Form for the topics API get query parameters.

base_fields = {'order_by': <django.forms.fields.ChoiceField object>, 'topic_id': <django.forms.fields.CharField object>}#
clean_topic_id()#
declared_fields = {'order_by': <django.forms.fields.ChoiceField object>, 'topic_id': <django.forms.fields.CharField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.UserCommentListGetForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None)#

Bases: _PaginationForm

A form to validate query parameters in the comment list retrieval endpoint

base_fields = {'course_id': <django.forms.fields.CharField object>, 'flagged': <django.forms.fields.BooleanField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>}#
clean_course_id()#

Validate course_id

declared_fields = {'course_id': <django.forms.fields.CharField object>, 'flagged': <django.forms.fields.BooleanField object>, 'page': <django.forms.fields.IntegerField object>, 'page_size': <django.forms.fields.IntegerField object>, 'requested_fields': <openedx.core.djangoapps.util.forms.MultiValueField object>}#
property media#

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

class lms.djangoapps.discussion.rest_api.forms.UserOrdering(value)#

Bases: TextChoices

An enumeration.

BY_ACTIVITY = 'activity'#
BY_FLAGS = 'flagged'#
BY_RECENT_ACTIVITY = 'recency'#

lms.djangoapps.discussion.rest_api.pagination module#

Discussion API pagination support

class lms.djangoapps.discussion.rest_api.pagination.DiscussionAPIPagination(request, page_num, num_pages, result_count=0)#

Bases: NamespacedPageNumberPagination

Subclasses NamespacedPageNumberPagination to provide custom implementation of pagination metadata by overriding it’s methods

Returns absolute url of the next page if there’s a next page available otherwise returns None

get_num_pages()#

Returns total number of pages the response is divided into

Returns absolute url of the previous page if there’s a previous page available otherwise returns None

get_result_count()#

Returns total number of results

lms.djangoapps.discussion.rest_api.permissions module#

Discussion API permission logic

class lms.djangoapps.discussion.rest_api.permissions.IsStaffOrAdmin#

Bases: BasePermission

Permission that checks if the user is staff or an admin.

has_permission(request, view)#

Returns true if the user is admin or staff and request method is GET.

class lms.djangoapps.discussion.rest_api.permissions.IsStaffOrCourseTeamOrEnrolled#

Bases: BasePermission

Permission that checks to see if the user is allowed to post or comment in the course.

has_permission(request, view)#

Returns true if the user is enrolled or is staff.

lms.djangoapps.discussion.rest_api.permissions.can_delete(cc_content, context)#

Return True if the requester can delete the given content, False otherwise

lms.djangoapps.discussion.rest_api.permissions.get_editable_fields(cc_content: Thread | Comment, context: Dict) Set[str]#

Return the set of fields that the requester can edit on the given content

lms.djangoapps.discussion.rest_api.permissions.get_initializable_comment_fields(context)#

Return the set of fields that the requester can initialize for a comment

Any field that is editable by the author should also be initializable.

lms.djangoapps.discussion.rest_api.permissions.get_initializable_thread_fields(context)#

Return the set of fields that the requester can initialize for a thread

Any field that is editable by the author should also be initializable.

lms.djangoapps.discussion.rest_api.render module#

Content rendering functionality

Note that this module is designed to imitate the front end behavior as implemented in Markdown.Sanitizer.js.

lms.djangoapps.discussion.rest_api.render.render_body(raw_body)#

Render raw_body to HTML.

This includes the following steps:

  • Convert Markdown to HTML

  • Sanitise HTML using bleach

Note that this does not prevent Markdown syntax inside a MathJax block from being processed, which the forums JavaScript code does.

lms.djangoapps.discussion.rest_api.serializers module#

Discussion API serializers

class lms.djangoapps.discussion.rest_api.serializers.BlackoutDateSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for blackout dates.

class lms.djangoapps.discussion.rest_api.serializers.CommentSerializer(*args, **kwargs)#

Bases: _ContentSerializer

A serializer for comment data.

N.B. This should not be used with a comment_client Comment object that has not had retrieve() called, because of the interaction between DRF’s attempts at introspection and Comment’s __getattr__.

create(validated_data)#
get_abuse_flagged_any_user(obj)#

Returns a boolean indicating whether any user has flagged the content as abusive.

get_children(obj)#
get_endorsed_at(obj)#

Returns the timestamp for the endorsement, if available. This information is unavailable outside the thread context.

get_endorsed_by(obj)#

Returns the username of the endorsing user, if the information is available and would not identify the author of an anonymous thread. This information is unavailable outside the thread context.

get_endorsed_by_label(obj)#

Returns the role label (i.e. “Staff” or “Community TA”) for the endorsing user. This information is unavailable outside the thread context.

non_updatable_fields = {'parent_id', 'thread_id'}#
to_representation(data)#

Object instance -> Dict of primitive datatypes.

update(instance, validated_data)#
validate(attrs)#

Ensure that parent_id identifies a comment that is actually in the thread identified by thread_id and does not violate the configured maximum depth.

class lms.djangoapps.discussion.rest_api.serializers.CourseMetadataSerailizer(*args, **kwargs)#

Bases: Serializer

Serializer for course metadata.

class lms.djangoapps.discussion.rest_api.serializers.DiscussionRolesListSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for course discussion roles member list.

create(validated_data)#

Overridden create abstract method

get_division_scheme(obj)#

Return the division scheme for the course.

get_results(obj)#

Return the nested serializer data representing a list of member users.

update(instance, validated_data)#

Overridden update abstract method

class lms.djangoapps.discussion.rest_api.serializers.DiscussionRolesMemberSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for course discussion roles member data.

create(validated_data)#

Overriden create abstract method

get_group_name(instance)#

Return the group name of the user.

update(instance, validated_data)#

Overriden update abstract method

class lms.djangoapps.discussion.rest_api.serializers.DiscussionRolesSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for course discussion roles.

ACTION_CHOICES = (('allow', 'allow'), ('revoke', 'revoke'))#
create(validated_data)#

Overriden create abstract method

update(instance, validated_data)#

Overriden update abstract method

validate(attrs)#

Validate the data at an object level.

validate_user_id(user_id)#

Validate user id :param user_id: username or email :type user_id: str

Returns:

user id if valid

Return type:

str

class lms.djangoapps.discussion.rest_api.serializers.DiscussionTopicSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for DiscussionTopic

create(validated_data)#

Overriden create abstract method

get_children(obj)#

Returns a list of children of DiscussionTopicSerializer type

update(instance, validated_data)#

Overriden update abstract method

class lms.djangoapps.discussion.rest_api.serializers.DiscussionTopicSerializerV2(*args, **kwargs)#

Bases: Serializer

Serializer for new style topics.

get_thread_counts(obj: DiscussionTopicLink) Dict[str, int]#

Get thread counts from provided context

class lms.djangoapps.discussion.rest_api.serializers.ReasonCodeSeralizer(*args, **kwargs)#

Bases: Serializer

Serializer for reason codes.

class lms.djangoapps.discussion.rest_api.serializers.ThreadSerializer(*args, **kwargs)#

Bases: _ContentSerializer

A serializer for thread data.

N.B. This should not be used with a comment_client Thread object that has not had retrieve() called, because of the interaction between DRF’s attempts at introspection and Thread’s __getattr__.

create(validated_data)#
get_abuse_flagged_count(obj)#

Returns the number of users that flagged content as abusive only if user has staff permissions

get_close_reason(obj)#

Returns the reason for which the thread was closed.

get_closed_by(obj)#

Returns the username of the moderator who closed this thread, only to other privileged users and author.

get_closed_by_label(obj)#

Returns the role label for the user who closed the post.

get_comment_count(obj)#

Increments comment count to include post and returns total count of contributions (i.e. post + responses + comments) for the thread

get_comment_list_url(obj, endorsed=None)#

Returns the URL to retrieve the thread’s comments, optionally including the endorsed query parameter.

get_endorsed_comment_list_url(obj)#

Returns the URL to retrieve the thread’s endorsed comments.

get_following(obj)#

Returns a boolean indicating whether the requester is following the thread.

get_group_name(obj)#

Returns the name of the group identified by the thread’s group_id.

get_non_endorsed_comment_list_url(obj)#

Returns the URL to retrieve the thread’s non-endorsed comments.

get_pinned(obj)#

Compensate for the fact that some threads in the comments service do not have the pinned field set.

get_preview_body(obj)#

Returns a cleaned version of the thread’s body to display in a preview capacity.

get_unread_comment_count(obj)#

Returns the number of unread comments. If the thread has never been read, this additionally includes 1 for the post itself, in addition to its responses and comments.

non_updatable_fields = {'course_id'}#
update(instance, validated_data)#
class lms.djangoapps.discussion.rest_api.serializers.TopicOrdering(value)#

Bases: TextChoices

Enum for the available options for ordering topics.

ACTIVITY = 'activity'#
COURSE_STRUCTURE = 'course_structure'#
NAME = 'name'#
class lms.djangoapps.discussion.rest_api.serializers.UserStatsSerializer(*args, **kwargs)#

Bases: Serializer

Serializer for course user stats.

to_representation(instance)#

Remove flag counts if user is not privileged.

lms.djangoapps.discussion.rest_api.serializers.get_context(course, request, thread=None)#

Returns a context appropriate for use with ThreadSerializer or (if thread is provided) CommentSerializer.

lms.djangoapps.discussion.rest_api.serializers.validate_close_reason_code(value)#

Validate that the value is a valid close reason code.

Raises: ValidationError

lms.djangoapps.discussion.rest_api.serializers.validate_edit_reason_code(value)#

Validate that the value is a valid edit reason code.

Raises: ValidationError

lms.djangoapps.discussion.rest_api.serializers.validate_not_blank(value)#

Validate that a value is not an empty string or whitespace.

Raises: ValidationError

lms.djangoapps.discussion.rest_api.tasks module#

Contain celery tasks

lms.djangoapps.discussion.rest_api.urls module#

Discussion API URLs

lms.djangoapps.discussion.rest_api.utils module#

Utils for discussion API.

class lms.djangoapps.discussion.rest_api.utils.AttributeDict#

Bases: dict

Converts Dict Keys into Attributes

class lms.djangoapps.discussion.rest_api.utils.DiscussionNotificationSender(thread, course, creator, parent_id=None)#

Bases: object

Class to send notifications to users who are subscribed to the thread.

send_new_comment_notification()#

Send notification to parent thread creator i.e. comment on the response.

send_new_comment_on_response_notification()#

Send notification to parent response creator i.e. comment on the response. Do not send notification if author of response is same as author of post.

send_new_response_notification()#

Send notification to users who are subscribed to the main thread/post i.e. there is a response to the main thread.

send_new_thread_created_notification()#

Send notification based on notification_type

lms.djangoapps.discussion.rest_api.utils.add_stats_for_users_with_no_discussion_content(course_stats, users_in_course)#

Update users stats for users with no discussion stats available in course

lms.djangoapps.discussion.rest_api.utils.add_thread_stats_to_subsection(topics_list)#

Add topic stats at subsection by adding stats of all units in the topic

lms.djangoapps.discussion.rest_api.utils.create_blocks_params(course_usage_key, user)#

Returns param dict that is needed to get blocks

lms.djangoapps.discussion.rest_api.utils.create_discussion_children_from_ids(children_ids, blocks, topics)#

Takes ids of discussion and return discussion dictionary

lms.djangoapps.discussion.rest_api.utils.create_topics_v3_structure(blocks, topics)#

Create V3 topics structure from blocks and v2 topics

lms.djangoapps.discussion.rest_api.utils.discussion_open_for_user(course, user)#

Check if the course discussion are open or not for user.

Parameters:
  • course – Course to check discussions for

  • user – User to check for privileges in course

lms.djangoapps.discussion.rest_api.utils.filter_topic_from_discussion_id(discussion_id, topics_list)#

Returns topic based on discussion id

lms.djangoapps.discussion.rest_api.utils.get_archived_topics(filtered_topic_ids: List[str], topics: List[Dict[str, str]]) List[Dict[str, str]]#

This function takes a list of topic ids and a list of topics, and returns the list of archived topics.

A topic is considered archived if it has a non-null usage_key field.

Args: - filtered_topic_ids (List[str]): A list of topic ids to filter on. - topics (List[Dict[str, str]]): A list of topic dictionaries. - Each dictionary should have a ‘id’ and a ‘usage_key’ field.

Returns: - A list of archived topic dictionaries, with the same format as the input topics.

lms.djangoapps.discussion.rest_api.utils.get_course_staff_users_list(course_id)#

Gets user ids for Staff roles for course discussions. Roles Course Instructor and Course Staff.

lms.djangoapps.discussion.rest_api.utils.get_course_ta_users_list(course_id)#

Gets user ids for TA roles for course discussions. Roles include Community TA and Group Community TA.

lms.djangoapps.discussion.rest_api.utils.get_moderator_users_list(course_id)#

Gets user ids for Moderator roles for course discussions. Roles include Discussion Administrator and Discussion Moderator.

lms.djangoapps.discussion.rest_api.utils.get_topic_ids_from_topics(topics: List[Dict[str, str]]) List[str]#

This function takes a list of topics and returns a list of the topic ids.

Args: - topics (List[Dict[str, str]]): A list of topic dictionaries. Each dictionary should have an ‘id’ field.

Returns: - A list of topic ids, extracted from the input list of topics.

lms.djangoapps.discussion.rest_api.utils.get_usernames_for_course(course_id, page_number, page_size)#

Gets usernames for all users in course.

Parameters:
  • course_id (CourseKey) – Course to check discussions for

  • page_number (int) – Page numbers to fetch

  • page_size (int) – Number of items in each page

Returns:

comma seperated usernames for the page matched_users_count (int): count of matched users in course matched_users_pages (int): pages of matched users in course

Return type:

page_matched_users (str)

lms.djangoapps.discussion.rest_api.utils.get_usernames_from_search_string(course_id, search_string, page_number, page_size)#

Gets usernames for all users in course that match string.

Parameters:
  • course_id (CourseKey) – Course to check discussions for

  • search_string (str) – String to search matching

  • page_number (int) – Page number to fetch

  • page_size (int) – Number of items in each page

Returns:

comma seperated usernames for the page matched_users_count (int): count of matched users in course matched_users_pages (int): pages of matched users in course

Return type:

page_matched_users (str)

lms.djangoapps.discussion.rest_api.utils.is_discussion_cohorted(course_key_str)#

Returns if the discussion is divided by cohorts

lms.djangoapps.discussion.rest_api.utils.is_posting_allowed(posting_restrictions: str, blackout_schedules: List)#

Check if posting is allowed based on the given posting restrictions and blackout schedules.

Parameters:
  • posting_restrictions (str) – Values would be “disabled”, “scheduled” or “enabled”.

  • blackout_schedules (List[Dict[str, datetime]]) – The list of blackout schedules

Returns:

True if posting is allowed, False otherwise.

Return type:

bool

lms.djangoapps.discussion.rest_api.utils.remove_empty_sequentials(data)#

Removes all objects of type “sequential” from a nested list of objects if they have no children. After removing the empty sequentials, if the parent of the sequential is now empty, it will also be removed. Parameters: data (list): A list of nested objects to check and remove empty sequentials from.

Returns: list: The modified list with empty sequentials removed.

lms.djangoapps.discussion.rest_api.utils.set_attribute(threads, attribute, value)#

Iterates over the list of dicts and assigns the provided value to the given attribute

Parameters:
  • threads – List of threads (dict objects)

  • attribute – the key for thread dict

  • value – the value to assign to the thread attribute

lms.djangoapps.discussion.rest_api.views module#

Discussion API views

class lms.djangoapps.discussion.rest_api.views.CommentViewSet(**kwargs)#

Bases: DeveloperErrorViewMixin, ViewSet

Use Cases

Retrieve the list of comments in a thread, retrieve the list of comments from an user in a course, retrieve the list of child comments for a response comment, create a comment, or modify or delete an existing comment.

Example Requests:

GET /api/discussion/v1/comments/?username=edx&course_id=course-v1:edX+DemoX+Demo_Course

GET /api/discussion/v1/comments/?username=edx&course_id=course-v1:edX+DemoX+Demo_Course&flagged=true

GET /api/discussion/v1/comments/?thread_id=0123456789abcdef01234567

GET /api/discussion/v1/comments/2123456789abcdef01234555

POST /api/discussion/v1/comments/ {

“thread_id”: “0123456789abcdef01234567”, “raw_body”: “Body text”

}

PATCH /api/discussion/v1/comments/comment_id {“raw_body”: “Edited text”} Content Type: “application/merge-patch+json”

DELETE /api/discussion/v1/comments/comment_id

GET Comment List Parameters:

  • thread_id (required when username is not provided): The thread to retrieve comments for

  • username (required when thread_id is not provided): The user from whom to retrieve comments

  • course_id (required when username is provided): The course from which to retrive the user’s comments

  • endorsed: If specified, only retrieve the endorsed or non-endorsed comments accordingly. Required for a question thread, must be absent for a discussion thread. This parameter has no effect when fetching comments by username.

  • flagged: Only retrieve comments that were flagged for abuse. This requires the requester to have elevated privileges, and has no effect otherwise.

  • page: The (1-indexed) page to retrieve (default is 1)

  • page_size: The number of items per page (default is 10, max is 100)

  • requested_fields: (list) Indicates which additional fields to return for each thread. (supports ‘profile_image’)

GET Child Comment List Parameters:

  • comment_id (required): The comment to retrieve child comments for

  • page: The (1-indexed) page to retrieve (default is 1)

  • page_size: The number of items per page (default is 10, max is 100)

  • requested_fields: (list) Indicates which additional fields to return for each thread. (supports ‘profile_image’)

POST Parameters:

  • thread_id (required): The thread to post the comment in

  • parent_id: The parent comment of the new comment. Can be null or omitted for a comment that should be directly under the thread

  • raw_body: The comment’s raw body text

  • anonymous (optional): A boolean indicating whether the comment is

anonymous; defaults to false

  • anonymous_to_peers (optional): A boolean indicating whether the

comment is anonymous to peers; defaults to false

PATCH Parameters:

  • raw_body, anonymous and anonymous_to_peers are accepted with the same

meaning as in a POST request

  • edit_reason_code (optional, privileged): A string containing a reason

code for a moderator to edit the comment.

If “application/merge-patch+json” is not the specified content type, a 415 error is returned.

GET Response Values:

  • results: The list of comments; each item in the list has the same

    fields as the POST response below

  • next: The URL of the next page (or null if first page)

  • previous: The URL of the previous page (or null if last page)

POST/PATCH Response Values:

  • id: The id of the comment

  • thread_id: The id of the comment’s thread

  • parent_id: The id of the comment’s parent

  • author: The username of the comment’s author, or None if the comment is anonymous

  • author_label: A label indicating whether the author has a special role in the course, either “Staff” for moderators and administrators or “Community TA” for community TAs

  • created_at: The ISO 8601 timestamp for the creation of the comment

  • updated_at: The ISO 8601 timestamp for the last modification of

    the comment, which may not have been an update of the body

  • raw_body: The comment’s raw body text without any rendering applied

  • endorsed: Boolean indicating whether the comment has been endorsed

    (by a privileged user or, for a question thread, the thread author)

  • endorsed_by: The username of the endorsing user, if available

  • endorsed_by_label: A label indicating whether the endorsing user

    has a special role in the course (see author_label)

  • endorsed_at: The ISO 8601 timestamp for the endorsement, if

    available

  • abuse_flagged: Boolean indicating whether the requesting user has flagged the comment for abuse

  • abuse_flagged_any_user: Boolean indicating whether any user has

    flagged the comment for abuse. Returns null if requesting user is not a moderator.

  • voted: Boolean indicating whether the requesting user has voted for the comment

  • vote_count: The number of votes for the comment

  • children: The list of child comments (with the same format)

  • editable_fields: The fields that the requesting user is allowed to

    modify with a PATCH request

  • anonymous: A boolean indicating whether the comment is anonymous

  • anonymous_to_peers: A boolean indicating whether the comment is

anonymous to peers

DELETE Response Value

No content is returned for a DELETE request

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

Implements the POST method for the list endpoint as described in the class docstring.

description = None#
destroy(request, comment_id)#

Implements the DELETE method for the instance endpoint as described in the class docstring

detail = None#
list(request)#

Implements the GET method for the list endpoint as described in the class docstring.

This endpoint implements two distinct usage contexts.

When username is provided, the course_id parameter is required, and thread_id is ignored. The behavior is to retrieve all of the user’s non-anonymous comments from the specified course, outside of the context of a forum thread. In this context, endorsement information is unavailable.

When username is not provided, thread_id is required, and course_id is ignored, since the thread already belongs to a course. In this context, all information relevant to usage in the discussions forum is available.

list_by_thread(request)#

Handles the case of fetching a thread’s comments.

list_by_user(request)#

Handles the case of fetching an user’s comments.

lookup_field = 'comment_id'#
name = None#
parser_classes = (<class 'rest_framework.parsers.JSONParser'>, <class 'openedx.core.lib.api.parsers.MergePatchParser'>)#
partial_update(request, comment_id)#

Implements the PATCH method for the instance endpoint as described in the class docstring.

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

Implements the GET method for comments against response ID

suffix = None#
class lms.djangoapps.discussion.rest_api.views.CourseActivityStatsView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

Use Cases

Fetch statistics about a user’s activity in a course.

Example Requests:

GET /api/discussion/v1/courses/course-v1:ExampleX+Subject101+2015/activity_stats?order_by=activity

Response Values:

Example Response ```json {

“pagination”: {

“count”: 3, “next”: null, “num_pages”: 1, “previous”: null

}, “results”: [

{

“active_flags”: 3, “inactive_flags”: 0, “replies”: 13, “responses”: 21, “threads”: 32, “username”: “edx”

}, {

“active_flags”: 1, “inactive_flags”: 0, “replies”: 6, “responses”: 8, “threads”: 13, “username”: “honor”

]

}#

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'>)#
get(request, course_key_string)#

Implements the GET method as described in the class docstring.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class lms.djangoapps.discussion.rest_api.views.CourseDiscussionRolesAPIView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

Use Cases Retrieve all the members of a given forum discussion role or update the membership of a role.

Example Requests

GET /api/discussion/v1/courses/{course_id}/roles/{rolename}

POST /api/discussion/v1/courses/{course_id}/roles/{rolename} {“user_id”: “<username or email>”, “action”: “<allow or revoke>”}

GET List Members of a Role Parameters:

  • course_id (required): The course to which the role belongs to.

  • rolename (required): The name of the forum discussion role, the members of which have to be listed. Currently supported values are ‘Moderator’, ‘Group Moderator’, ‘Community TA’. If the value has a space it has to be URL encoded.

POST Update the membership of a Role Parameters:

  • course_id (required): The course to which the role belongs to.

  • rolename (required): The name of the forum discussion role, the members of which have to be listed. Currently supported values are ‘Moderator’, ‘Group Moderator’, ‘Community TA’. If the value has a space it has to be URL encoded.

The body can use either ‘application/x-www-form-urlencoded’ or ‘application/json’ content type.

  • user_id (required): The username or email address of the user whose membership has to be updated.

  • action (required): Either ‘allow’ or ‘revoke’, depending on the action to be performed on the membership.

GET and POST Response Values:

A HTTP 404 Not Found response status code is returned when the requested course is invalid.

A HTTP 400 Bad Request response status code is returned when the request is invalid.

A HTTP 200 OK response status denote is returned to denote success.

  • course_id: The course to which the role belongs to.

  • results: A list of the members belonging to the specified role.

    • username: Username of the user.

    • email: Email address of the user.

    • first_name: First name of the user.

    • last_name: Last name of the user.

    • group_name: Name of the group the user belongs to.

  • division_scheme: The division scheme used by the course.

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'>)#
get(request, course_id, rolename)#

Implement a handler for the GET method.

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

Implement a handler for the POST method.

class lms.djangoapps.discussion.rest_api.views.CourseDiscussionSettingsAPIView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

Use Cases Retrieve all the discussion settings for a course or update one or more of them.

Example Requests

GET /api/discussion/v1/courses/{course_id}/settings

PATCH /api/discussion/v1/courses/{course_id}/settings {“always_divide_inline_discussions”: true}

GET Discussion Settings Parameters:

  • course_id (required): The course to retrieve the discussion settings for.

PATCH Discussion Settings Parameters:

  • course_id (required): The course to retrieve the discussion settings for.

The body should have the ‘application/merge-patch+json’ content type.

  • divided_inline_discussions: A list of IDs of the topics to be marked as divided inline discussions.

  • divided_course_wide_discussions: A list of IDs of the topics to be marked as divided course-wide discussions.

  • always_divide_inline_discussions: A boolean indicating whether inline discussions should always be divided or not.

  • division_scheme: A string corresponding to the division scheme to be used from the list of available division schemes.

GET and PATCH Discussion Settings Parameters Response Values:

A HTTP 404 Not Found response status code is returned when the requested course is invalid.

A HTTP 400 Bad Request response status code is returned when the request is invalid.

A HTTP 200 OK response status denote is returned to denote success.

  • id: The discussion settings id.

  • divided_inline_discussions: A list of divided inline discussions.

  • divided_course_wide_discussions: A list of divided course-wide discussions.

  • division_scheme: The division scheme used for the course discussions.

  • available_division_schemes: A list of available division schemes for the course.

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'>)#
get(request, course_id)#

Implement a handler for the GET method.

parser_classes = (<class 'rest_framework.parsers.JSONParser'>, <class 'openedx.core.lib.api.parsers.MergePatchParser'>)#
patch(request, course_id)#

Implement a handler for the PATCH method.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>, <class 'lms.djangoapps.discussion.rest_api.permissions.IsStaffOrAdmin'>)#
class lms.djangoapps.discussion.rest_api.views.CourseTopicsView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

Use Cases

Retrieve the topic listing for a course. Only topics accessible to the authenticated user are included.

Example Requests:

GET /api/discussion/v1/course_topics/course-v1:ExampleX+Subject101+2015

?topic_id={topic_id_1, topid_id_2}

Response Values:
  • courseware_topics: The list of topic trees for courseware-linked

    topics. Each item in the list includes:

    • id: The id of the discussion topic (null for a topic that only has children but cannot contain threads itself).

    • name: The display name of the topic.

    • children: A list of child subtrees of the same format.

  • non_courseware_topics: The list of topic trees that are not linked to

    courseware. Items are of the same format as in courseware_topics.

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'>)#
get(request, course_id)#

Implements the GET method as described in the class docstring.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class lms.djangoapps.discussion.rest_api.views.CourseTopicsViewV2(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

View for listing course topics.

For more information visit the [API Documentation](/api-docs/?filter=discussion#/discussion/discussion_v2_course_topics_read)

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'>)#
get(request, course_id)#

Use Cases

Retrieve the topic listing for a course.

Example Requests:

GET /api/discussion/v2/course_topics/course-v1:ExampleX+Subject101+2015

?topic_id={topic_id_1, topid_id_2}&order_by=course_structure

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class lms.djangoapps.discussion.rest_api.views.CourseTopicsViewV3(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

View for listing course topics v3.

** Response Example **: [

{

“id”: “non-courseware-discussion-id”, “usage_key”: None, “name”: “Non Courseware Topic”, “thread_counts”: {“discussion”: 0, “question”: 0}, “enabled_in_context”: true, “courseware”: false

}, {

“id”: “id”, “block_id”: “block_id”, “lms_web_url”: “”, “legacy_web_url”: “”, “student_view_url”: “”, “type”: “chapter”, “display_name”: “First section”, “children”: [

“id”: “id”, “block_id”: “block_id”, “lms_web_url”: “”, “legacy_web_url”: “”, “student_view_url”: “”, “type”: “sequential”, “display_name”: “First Sub-Section”, “children”: [

“id”: “id”, “usage_key”: “”, “name”: “First Unit?”, “thread_counts”: { “discussion”: 0, “question”: 0 }, “enabled_in_context”: true

]

], “courseware”: true,

}

]

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'>)#
get(request, course_id)#

Use Cases

Retrieve the topic listing for a course.

Example Requests:

GET /api/discussion/v3/course_topics/course-v1:ExampleX+Subject101+2015

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class lms.djangoapps.discussion.rest_api.views.CourseView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

General discussion metadata API.

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'>)#
get(request, course_id)#

Retrieve general discussion metadata for a course.

Example Requests:

GET /api/discussion/v1/courses/course-v1:ExampleX+Subject101+2015

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)#
class lms.djangoapps.discussion.rest_api.views.LearnerThreadView(**kwargs)#

Bases: APIView

Use Cases

Fetch user’s active threads

Example Requests:

GET /api/discussion/v1/courses/course-v1:ExampleX+Subject101+2015/learner/?username=edx&page=1&page_size=10

GET Thread List Parameters:

  • username: (Required) Username of the user whose active threads are required

  • page: The (1-indexed) page to retrieve (default is 1)

  • page_size: The number of items per page (default is 10)

  • count_flagged: If True, return the count of flagged comments for each thread.

(can only be used by moderators or above)

  • thread_type: The type of thread to filter None, “discussion” or “question”.

  • order_by: Sort order for threads “last_activity_at”, “comment_count” or

“vote_count”.

  • status: Filter for threads “flagged”, “unanswered”, “unread”.

  • group_id: Filter threads w.r.t cohorts (Cohort ID).

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthentication'>, <class 'rest_framework.authentication.SessionAuthentication'>)#
get(request, course_id=None)#

Implements the GET method as described in the class docstring.

permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>, <class 'lms.djangoapps.discussion.rest_api.permissions.IsStaffOrCourseTeamOrEnrolled'>)#
class lms.djangoapps.discussion.rest_api.views.ReplaceUsernamesView(**kwargs)#

Bases: APIView

WARNING: This API is only meant to be used as part of a larger job that updates usernames across all services. DO NOT run this alone or users will not match across the system and things will be broken.

API will recieve a list of current usernames and their new username.

POST /api/discussion/v1/accounts/replace_usernames/
{
“username_mappings”: [

{“current_username_1”: “desired_username_1”}, {“current_username_2”: “desired_username_2”}

]

}

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>,)#
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>, <class 'openedx.core.djangoapps.user_api.accounts.permissions.CanReplaceUsername'>)#
post(request)#

Implements the username replacement endpoint

class lms.djangoapps.discussion.rest_api.views.RetireUserView(**kwargs)#

Bases: APIView

Use Cases

A superuser or the user with the settings.RETIREMENT_SERVICE_WORKER_USERNAME can “retire” the user’s data from the comments service, which will remove personal information and blank all posts / comments the user has made.

Example Requests:

POST /api/discussion/v1/retire_user/ {

“username”: “an_original_user_name”

}

Example Response:

Empty string

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>,)#
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>, <class 'openedx.core.djangoapps.user_api.accounts.permissions.CanRetireUser'>)#
post(request)#

Implements the retirement endpoint.

class lms.djangoapps.discussion.rest_api.views.ThreadViewSet(**kwargs)#

Bases: DeveloperErrorViewMixin, ViewSet

Use Cases

Retrieve the list of threads for a course, retrieve thread details, post a new thread, or modify or delete an existing thread.

Example Requests:

GET /api/discussion/v1/threads/?course_id=ExampleX/Demo/2015

GET /api/discussion/v1/threads/{thread_id}

POST /api/discussion/v1/threads {

“course_id”: “foo/bar/baz”, “topic_id”: “quux”, “type”: “discussion”, “title”: “Title text”, “raw_body”: “Body text”

}

PATCH /api/discussion/v1/threads/thread_id {“raw_body”: “Edited text”} Content Type: “application/merge-patch+json”

DELETE /api/discussion/v1/threads/thread_id

GET Thread List Parameters:

  • course_id (required): The course to retrieve threads for

  • page: The (1-indexed) page to retrieve (default is 1)

  • page_size: The number of items per page (default is 10, max is 100)

  • topic_id: The id of the topic to retrieve the threads. There can be

    multiple topic_id queries to retrieve threads from multiple topics at once.

  • author: The username of an author. If provided, only threads by this

    author will be returned.

  • thread_type: Can be ‘discussion’ or ‘question’, only return threads of

    the selected thread type.

  • flagged: If True, only return threads that have been flagged (reported)

  • count_flagged: If True, return the count of flagged comments for each thread. (can only be used by moderators or above)

  • text_search: A search string to match. Any thread whose content

    (including the bodies of comments in the thread) matches the search string will be returned.

  • order_by: Must be “last_activity_at”, “comment_count”, or

    “vote_count”. The key to sort the threads by. The default is “last_activity_at”.

  • order_direction: Must be “desc”. The direction in which to sort the

    threads by. The default and only value is “desc”. This will be removed in a future major version.

  • following: If true, retrieve only threads the requesting user is

    following

  • view: “unread” for threads the requesting user has not read, or

    “unanswered” for question threads with no marked answer. Only one can be selected, or unresponded for discussion type posts with no response

  • requested_fields: (list) Indicates which additional fields to return for each thread. (supports ‘profile_image’)

The topic_id, text_search, and following parameters are mutually exclusive (i.e. only one may be specified in a request)

GET Thread Parameters:

  • thread_id (required): The id of the thread

  • requested_fields (optional parameter): (list) Indicates which additional

fields to return for each thread. (supports ‘profile_image’)

POST Parameters:

  • course_id (required): The course to create the thread in

  • topic_id (required): The topic to create the thread in

  • type (required): The thread’s type (either “question” or “discussion”)

  • title (required): The thread’s title

  • raw_body (required): The thread’s raw body text

  • following (optional): A boolean indicating whether the user should

    follow the thread upon its creation; defaults to false

  • anonymous (optional): A boolean indicating whether the post is

anonymous; defaults to false

  • anonymous_to_peers (optional): A boolean indicating whether the post

is anonymous to peers; defaults to false

PATCH Parameters:

  • abuse_flagged (optional): A boolean to mark thread as abusive

  • voted (optional): A boolean to vote for thread

  • read (optional): A boolean to mark thread as read

  • closed (optional, privileged): A boolean to mark thread as closed.

  • edit_reason_code (optional, privileged): A string containing a reason

code for editing the thread’s body.

  • close_reason_code (optional, privileged): A string containing a reason

code for closing the thread.

  • topic_id, type, title, raw_body, anonymous, and anonymous_to_peers

are accepted with the same meaning as in a POST request

If “application/merge-patch+json” is not the specified content type, a 415 error is returned.

GET Thread List Response Values:

  • results: The list of threads; each item in the list has the same

    fields as the POST/PATCH response below

  • next: The URL of the next page (or null if first page)

  • previous: The URL of the previous page (or null if last page)

  • text_search_rewrite: The search string to which the text_search

    parameter was rewritten in order to match threads (e.g. for spelling correction)

GET Thread Details Response Values:

Same response fields as the POST/PATCH response below

POST/PATCH response values:

  • id: The id of the thread

  • course_id: The id of the thread’s course

  • topic_id: The id of the thread’s topic

  • created_at: The ISO 8601 timestamp for the creation of the thread

  • updated_at: The ISO 8601 timestamp for the last modification of

    the thread, which may not have been an update of the title/body

  • type: The thread’s type (either “question” or “discussion”)

  • title: The thread’s title

  • raw_body: The thread’s raw body text without any rendering applied

  • pinned: Boolean indicating whether the thread has been pinned

  • closed: Boolean indicating whether the thread has been closed

  • comment_count: The number of comments within the thread

  • unread_comment_count: The number of comments within the thread

    that were created or updated since the last time the user read the thread

  • editable_fields: The fields that the requesting user is allowed to

    modify with a PATCH request

  • read: Boolean indicating whether the user has read this thread

  • has_endorsed: Boolean indicating whether this thread has been answered

  • response_count: The number of direct responses for a thread

  • abuse_flagged_count: The number of flags(reports) on and within the

    thread. Returns null if requesting user is not a moderator

  • anonymous: A boolean indicating whether the post is anonymous

  • anonymous_to_peers: A boolean indicating whether the post is

anonymous to peers

**DELETE response values:

No content is returned for a DELETE request

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

Implements the POST method for the list endpoint as described in the class docstring.

description = None#
destroy(request, thread_id)#

Implements the DELETE method for the instance endpoint as described in the class docstring

detail = None#
list(request)#

Implements the GET method for the list endpoint as described in the class docstring.

lookup_field = 'thread_id'#
name = None#
parser_classes = (<class 'rest_framework.parsers.JSONParser'>, <class 'openedx.core.lib.api.parsers.MergePatchParser'>)#
partial_update(request, thread_id)#

Implements the PATCH method for the instance endpoint as described in the class docstring.

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

Implements the GET method for thread ID

suffix = None#
class lms.djangoapps.discussion.rest_api.views.UploadFileView(**kwargs)#

Bases: DeveloperErrorViewMixin, APIView

Use Cases

Upload a file to be attached to a thread or comment.

URL Parameters

  • course_id:

    The ID of the course where this thread or comment belongs.

POST Upload File Parameters

  • thread_key:

    If the upload belongs to a comment, refer to the parent thread_id, otherwise it should be “root”.

Example Requests:

POST /api/discussion/v1/courses/{course_id}/upload/ Content-Type: multipart/form-data; boundary=–Boundary

—-Boundary Content-Disposition: form-data; name=”thread_key”

<thread_key> —-Boundary Content-Disposition: form-data; name=”uploaded_file”; filename=”<filename>.<ext>” Content-Type: <mimetype>

<file_content> —-Boundary–

Response Values

  • location: The URL to access the uploaded file.

authentication_classes = (<class 'edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication'>, <class 'openedx.core.lib.api.authentication.BearerAuthentication'>, <class 'rest_framework.authentication.SessionAuthentication'>)#
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>, <class 'lms.djangoapps.discussion.rest_api.permissions.IsStaffOrCourseTeamOrEnrolled'>)#
post(request, course_id)#

Handles a file upload.

Module contents#