Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
9c32b1e8
Commit
9c32b1e8
authored
Apr 21, 2015
by
Diana Huang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor course_structure_api to have separate
API Layer.
parent
7df9ab9c
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
140 additions
and
22 deletions
+140
-22
lms/djangoapps/course_structure_api/v0/api.py
+94
-0
lms/djangoapps/course_structure_api/v0/errors.py
+9
-0
lms/djangoapps/course_structure_api/v0/views.py
+37
-22
No files found.
lms/djangoapps/course_structure_api/v0/api.py
0 → 100644
View file @
9c32b1e8
"""
API implementation of the Course Structure API for Python code.
Note: The course list and course detail functionality isn't currently supported here because of the tricky interactions between DRF and the code.
Most of that information is available by accessing the course objects directly.
"""
from
course_structure_api.v0
import
serializers
from
course_structure_api.v0.errors
import
CourseNotFoundError
,
CourseStructureNotAvailableError
from
openedx.core.djangoapps.content.course_structures
import
models
,
tasks
from
courseware
import
courses
def
_retrieve_course
(
course_key
):
"""Retrieves the course for the given course key.
Args:
course_key: The CourseKey for the course we'd like to retrieve.
Returns:
the course that matches the CourseKey
Raises:
CourseNotFoundError
"""
try
:
course
=
courses
.
get_course
(
course_key
)
return
course
except
ValueError
:
raise
CourseNotFoundError
def
course_structure
(
course_key
):
"""
Retrieves the entire course structure, including information about all the blocks used in the course.
Args:
course_key: the CourseKey of the course we'd like to retrieve.
Returns:
The serialized output of the course structure:
* root: The ID of the root node of the course structure.
* blocks: A dictionary that maps block IDs to a collection of
information about each block. Each block contains the following
fields.
* id: The ID of the block.
* type: The type of block. Possible values include sequential,
vertical, html, problem, video, and discussion. The type can also be
the name of a custom type of block used for the course.
* display_name: The display name configured for the block.
* graded: Whether or not the sequential or problem is graded. The
value is true or false.
* format: The assignment type.
* children: If the block has child blocks, a list of IDs of the child
blocks.
Raises:
CourseStructureNotAvailableError, CourseNotFoundError
"""
course
=
_retrieve_course
(
course_key
)
try
:
course_structure
=
models
.
CourseStructure
.
objects
.
get
(
course_id
=
course
.
id
)
return
serializers
.
CourseStructureSerializer
(
course_structure
.
structure
)
.
data
except
models
.
CourseStructure
.
DoesNotExist
:
# If we don't have data stored, generate it and return an error.
tasks
.
update_course_structure
.
delay
(
unicode
(
course_key
))
raise
CourseStructureNotAvailableError
def
course_grading_policy
(
course_key
):
"""
Retrieves the course grading policy.
Args:
course_key: CourseKey the corresponds to the course we'd like to know grading policy information about.
Returns:
The serialized version of the course grading policy containing the following information:
* assignment_type: The type of the assignment, as configured by course
staff. For example, course staff might make the assignment types Homework,
Quiz, and Exam.
* count: The number of assignments of the type.
* dropped: Number of assignments of the type that are dropped.
* weight: The weight, or effect, of the assignment type on the learner's
final grade.
"""
course
=
_retrieve_course
(
course_key
)
return
serializers
.
GradingPolicySerializer
(
course
.
raw_grader
)
.
data
lms/djangoapps/course_structure_api/v0/errors.py
0 → 100644
View file @
9c32b1e8
class
CourseNotFoundError
(
Exception
):
""" The course was not found. """
pass
class
CourseStructureNotAvailableError
(
Exception
):
""" The course structure still needs to be generated. """
pass
lms/djangoapps/course_structure_api/v0/views.py
View file @
9c32b1e8
...
...
@@ -11,7 +11,8 @@ from rest_framework.response import Response
from
xmodule.modulestore.django
import
modulestore
from
opaque_keys.edx.keys
import
CourseKey
from
course_structure_api.v0
import
serializers
from
course_structure_api.v0
import
api
,
serializers
from
course_structure_api.v0.errors
import
CourseNotFoundError
,
CourseStructureNotAvailableError
from
courseware
import
courses
from
courseware.access
import
has_access
from
openedx.core.djangoapps.content.course_structures
import
models
,
tasks
...
...
@@ -40,13 +41,37 @@ class CourseViewMixin(object):
course_id
=
self
.
kwargs
.
get
(
'course_id'
)
course_key
=
CourseKey
.
from_string
(
course_id
)
course
=
courses
.
get_course
(
course_key
)
self
.
check_course_permissions
(
self
.
request
.
user
,
course
)
self
.
check_course_permissions
(
self
.
request
.
user
,
course_key
)
return
course
except
ValueError
:
raise
Http404
@staticmethod
def
course_check
(
func
):
"""Decorator responsible for catching errors finding and returning a 404 if the user does not have access
to the API function.
:param func: function to be wrapped
:returns: the wrapped function
"""
def
func_wrapper
(
self
,
*
args
,
**
kwargs
):
"""Wrapper function for this decorator.
:param *args: the arguments passed into the function
:param **kwargs: the keyword arguments passed into the function
:returns: the result of the wrapped function
"""
try
:
course_id
=
self
.
kwargs
.
get
(
'course_id'
)
self
.
course_key
=
CourseKey
.
from_string
(
course_id
)
self
.
check_course_permissions
(
self
.
request
.
user
,
self
.
course_key
)
return
func
(
self
,
*
args
,
**
kwargs
)
except
CourseNotFoundError
:
raise
Http404
return
func_wrapper
def
user_can_access_course
(
self
,
user
,
course
):
"""
Determines if the user is staff or an instructor for the course.
...
...
@@ -185,7 +210,6 @@ class CourseDetail(CourseViewMixin, RetrieveAPIView):
* end: The course end date. If course end date is not specified, the
value is null.
"""
serializer_class
=
serializers
.
CourseSerializer
def
get_object
(
self
,
queryset
=
None
):
...
...
@@ -227,22 +251,16 @@ class CourseStructure(CourseViewMixin, RetrieveAPIView):
* children: If the block has child blocks, a list of IDs of the child
blocks.
"""
serializer_class
=
serializers
.
CourseStructureSerializer
course
=
None
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
@CourseViewMixin.course_check
def
get
(
self
,
request
,
course_id
=
None
):
try
:
return
super
(
CourseStructure
,
self
)
.
retrieve
(
request
,
*
args
,
**
kwargs
)
except
models
.
CourseStructure
.
DoesNotExist
:
# If we don't have data stored,
generate it and return a 503.
tasks
.
update_course_structure
.
delay
(
unicode
(
self
.
course
.
id
))
return
Response
(
api
.
course_structure
(
self
.
course_key
)
)
except
CourseStructureNotAvailableError
:
# If we don't have data stored,
we will try to regenerate it, so
# return a 503 and as them to retry in 2 minutes.
return
Response
(
status
=
503
,
headers
=
{
'Retry-After'
:
'120'
})
def
get_object
(
self
,
queryset
=
None
):
# Make sure the course exists and the user has permissions to view it.
self
.
course
=
self
.
get_course_or_404
()
course_structure
=
models
.
CourseStructure
.
objects
.
get
(
course_id
=
self
.
course
.
id
)
return
course_structure
.
structure
class
CourseGradingPolicy
(
CourseViewMixin
,
ListAPIView
):
...
...
@@ -269,11 +287,8 @@ class CourseGradingPolicy(CourseViewMixin, ListAPIView):
final grade.
"""
serializer_class
=
serializers
.
GradingPolicySerializer
allow_empty
=
False
def
get_queryset
(
self
):
course
=
self
.
get_course_or_404
()
# Return the raw data. The serializer will handle the field mappings.
return
course
.
raw_grader
@CourseViewMixin.course_check
def
get
(
self
,
request
,
course_id
=
None
):
return
Response
(
api
.
course_grading_policy
(
self
.
course_key
))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment