feat: upgrading list_instructor_tasks to DRF ( 10th ) (#35332)
* feat: upgrading simple api to drf compatible.
This commit is contained in:
@@ -4704,15 +4704,19 @@ class TestOauthInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollm
|
||||
Test endpoints using Oauth2 authentication.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create(
|
||||
entrance_exam_id='i4x://{}/{}/chapter/Entrance_exam'.format('test_org', 'test_course')
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(
|
||||
org='test_org',
|
||||
course='test_course',
|
||||
run='test_run',
|
||||
entrance_exam_id='i4x://{}/{}/chapter/Entrance_exam'.format('test_org', 'test_course')
|
||||
)
|
||||
self.problem_location = msk_from_problem_urlname(
|
||||
self.course.id,
|
||||
'robot-some-problem-urlname'
|
||||
)
|
||||
self.problem_urlname = str(self.problem_location)
|
||||
|
||||
self.other_user = UserFactory()
|
||||
dot_application = ApplicationFactory(user=self.other_user, authorization_grant_type='password')
|
||||
@@ -4744,7 +4748,14 @@ class TestOauthInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollm
|
||||
"send-to": ["myself"],
|
||||
"subject": "This is subject",
|
||||
"message": "message"
|
||||
}, 'data_researcher')
|
||||
}, 'data_researcher'),
|
||||
('list_instructor_tasks',
|
||||
{
|
||||
'problem_location_str': self.problem_urlname,
|
||||
'unique_student_identifier': self.other_user.email
|
||||
},
|
||||
'data_researcher'),
|
||||
('list_instructor_tasks', {}, 'data_researcher')
|
||||
]
|
||||
|
||||
self.fake_jwt = ('wyJUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjaGFuZ2UtbWUiLCJleHAiOjE3MjU4OTA2NzIsImdyY'
|
||||
|
||||
@@ -108,7 +108,7 @@ from lms.djangoapps.instructor_task.data import InstructorTaskTypes
|
||||
from lms.djangoapps.instructor_task.models import ReportStore
|
||||
from lms.djangoapps.instructor.views.serializer import (
|
||||
AccessSerializer, BlockDueDateSerializer, RoleNameSerializer, ShowStudentExtensionSerializer, UserSerializer,
|
||||
SendEmailSerializer, StudentAttemptsSerializer
|
||||
SendEmailSerializer, StudentAttemptsSerializer, ListInstructorTaskInputSerializer
|
||||
)
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, is_course_cohorted
|
||||
@@ -2373,9 +2373,8 @@ class InstructorTasks(DeveloperErrorViewMixin, APIView):
|
||||
return _list_instructor_tasks(request=request, course_id=course_id)
|
||||
|
||||
|
||||
@require_POST
|
||||
@ensure_csrf_cookie
|
||||
def list_instructor_tasks(request, course_id):
|
||||
@method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True), name='dispatch')
|
||||
class ListInstructorTasks(APIView):
|
||||
"""
|
||||
List instructor tasks.
|
||||
|
||||
@@ -2385,21 +2384,44 @@ def list_instructor_tasks(request, course_id):
|
||||
- `problem_location_str` and `unique_student_identifier` lists task
|
||||
history for problem AND student (intersection)
|
||||
"""
|
||||
return _list_instructor_tasks(request=request, course_id=course_id)
|
||||
permission_classes = (IsAuthenticated, permissions.InstructorPermission)
|
||||
permission_name = permissions.SHOW_TASKS
|
||||
serializer_class = ListInstructorTaskInputSerializer
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def post(self, request, course_id):
|
||||
"""
|
||||
List instructor tasks.
|
||||
"""
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
return _list_instructor_tasks(
|
||||
request=request, course_id=course_id, serialize_data=serializer.validated_data
|
||||
)
|
||||
|
||||
|
||||
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
||||
@require_course_permission(permissions.SHOW_TASKS)
|
||||
def _list_instructor_tasks(request, course_id):
|
||||
def _list_instructor_tasks(request, course_id, serialize_data=None):
|
||||
"""
|
||||
List instructor tasks.
|
||||
|
||||
Internal function with common code for both DRF and and tradition views.
|
||||
"""
|
||||
# This method is also used by other APIs with the GET method.
|
||||
# The query_params attribute is utilized for GET requests,
|
||||
# where parameters are passed as query strings.
|
||||
|
||||
course_id = CourseKey.from_string(course_id)
|
||||
params = getattr(request, 'query_params', request.POST)
|
||||
problem_location_str = strip_if_string(params.get('problem_location_str', False))
|
||||
student = params.get('unique_student_identifier', None)
|
||||
if serialize_data is not None:
|
||||
problem_location_str = strip_if_string(serialize_data.get('problem_location_str', False))
|
||||
student = serialize_data.get('unique_student_identifier', None)
|
||||
else:
|
||||
params = getattr(request, 'query_params', request.POST)
|
||||
problem_location_str = strip_if_string(params.get('problem_location_str', False))
|
||||
student = params.get('unique_student_identifier', None)
|
||||
|
||||
if student is not None:
|
||||
student = get_student_from_identifier(student)
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ urlpatterns = [
|
||||
name='list_entrance_exam_instructor_tasks'),
|
||||
path('mark_student_can_skip_entrance_exam', api.mark_student_can_skip_entrance_exam,
|
||||
name='mark_student_can_skip_entrance_exam'),
|
||||
path('list_instructor_tasks', api.list_instructor_tasks, name='list_instructor_tasks'),
|
||||
path('list_instructor_tasks', api.ListInstructorTasks.as_view(), name='list_instructor_tasks'),
|
||||
path('list_background_email_tasks', api.list_background_email_tasks, name='list_background_email_tasks'),
|
||||
path('list_email_content', api.ListEmailContent.as_view(), name='list_email_content'),
|
||||
path('list_forum_members', api.list_forum_members, name='list_forum_members'),
|
||||
|
||||
@@ -61,6 +61,43 @@ class AccessSerializer(serializers.Serializer):
|
||||
return user
|
||||
|
||||
|
||||
class ListInstructorTaskInputSerializer(serializers.Serializer): # pylint: disable=abstract-method
|
||||
"""
|
||||
Serializer for handling the input data for the problem response report generation API.
|
||||
|
||||
Attributes:
|
||||
unique_student_identifier (str): The email or username of the student.
|
||||
This field is optional, but if provided, the `problem_location_str`
|
||||
must also be provided.
|
||||
problem_location_str (str): The string representing the location of the problem within the course.
|
||||
This field is optional, unless `unique_student_identifier` is provided.
|
||||
"""
|
||||
unique_student_identifier = serializers.CharField(
|
||||
max_length=255,
|
||||
help_text="Email or username of student",
|
||||
required=False
|
||||
)
|
||||
problem_location_str = serializers.CharField(
|
||||
help_text="Problem location",
|
||||
required=False
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
"""
|
||||
Validate the data to ensure that if unique_student_identifier is provided,
|
||||
problem_location_str must also be provided.
|
||||
"""
|
||||
unique_student_identifier = data.get('unique_student_identifier')
|
||||
problem_location_str = data.get('problem_location_str')
|
||||
|
||||
if unique_student_identifier and not problem_location_str:
|
||||
raise serializers.ValidationError(
|
||||
"unique_student_identifier must accompany problem_location_str"
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class ShowStudentExtensionSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for validating and processing the student identifier.
|
||||
|
||||
Reference in New Issue
Block a user