Merge pull request #6760 from edx/markhoeber-doc1510
Platform API Doc Update
This commit is contained in:
16
docs/en_us/platform_api/source/change_log.rst
Normal file
16
docs/en_us/platform_api/source/change_log.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
############
|
||||
Change Log
|
||||
############
|
||||
|
||||
*****************
|
||||
January, 2015
|
||||
*****************
|
||||
|
||||
.. list-table::
|
||||
:widths: 10 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Date
|
||||
- Change
|
||||
* - 29 January 2015
|
||||
- Added the :ref:`Get or Change User Status in a Course` section.
|
||||
@@ -7,6 +7,17 @@
|
||||
import os
|
||||
from path import path
|
||||
import sys
|
||||
import mock
|
||||
|
||||
MOCK_MODULES = ['lxml', 'requests', 'xblock', 'fields', 'xblock.fields',
|
||||
'frament', 'xblock.fragment', 'webob', 'multidict', 'webob.multidict', 'core',
|
||||
'xblock.core', 'runtime', 'xblock.runtime', 'sortedcontainers', 'contracts',
|
||||
'plugin', 'xblock.plugin', 'opaque_keys.edx.asides', 'asides',
|
||||
'dogstats_wrapper', 'fs', 'fs.errors', 'edxmako', 'edxmako.shortcuts',
|
||||
'shortcuts', 'crum', 'opaque_keys.edx.locator', 'LibraryLocator', 'Location']
|
||||
|
||||
for mod_name in MOCK_MODULES:
|
||||
sys.modules[mod_name] = mock.Mock()
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
@@ -35,6 +46,8 @@ if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
root = path('../../../..').abspath()
|
||||
sys.path.insert(0, root)
|
||||
sys.path.append(root / "common/lib/xmodule")
|
||||
sys.path.append(root / "lms/djangoapps")
|
||||
sys.path.append(root / "lms/djangoapps/mobile_api")
|
||||
sys.path.append(root / "lms/djangoapps/mobile_api/course_info")
|
||||
sys.path.append(root / "lms/djangoapps/mobile_api/users")
|
||||
@@ -54,7 +67,7 @@ sys.path.append('.')
|
||||
if on_rtd:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'lms'
|
||||
else:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'lms.envs.test'
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'lms'
|
||||
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
@@ -66,164 +79,9 @@ extensions = [
|
||||
'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath',
|
||||
'sphinx.ext.mathjax', 'sphinx.ext.viewcode', 'sphinxcontrib.napoleon']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['build']
|
||||
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'edXDocs'
|
||||
|
||||
project = u'edX Platform API Version 0.5 Alpha'
|
||||
copyright = u'2014, edX'
|
||||
copyright = u'2015, edX'
|
||||
|
||||
# --- Mock modules ------------------------------------------------------------
|
||||
|
||||
# Mock all the modules that the readthedocs build can't import
|
||||
exclude_patterns = ['build', 'links.rst']
|
||||
|
||||
|
||||
class Mock(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return Mock()
|
||||
|
||||
@classmethod
|
||||
def __getattr__(cls, name):
|
||||
if name in ('__file__', '__path__'):
|
||||
return '/dev/null'
|
||||
elif name[0] == name[0].upper():
|
||||
mockType = type(name, (), {})
|
||||
mockType.__module__ = __name__
|
||||
return mockType
|
||||
else:
|
||||
return Mock()
|
||||
|
||||
# The list of modules and submodules that we know give RTD trouble.
|
||||
# Make sure you've tried including the relevant package in
|
||||
# docs/share/requirements.txt before adding to this list.
|
||||
MOCK_MODULES = [
|
||||
'bson',
|
||||
'bson.errors',
|
||||
'bson.objectid',
|
||||
'dateutil',
|
||||
'dateutil.parser',
|
||||
'fs',
|
||||
'fs.errors',
|
||||
'fs.osfs',
|
||||
'lazy',
|
||||
'mako',
|
||||
'mako.template',
|
||||
'matplotlib',
|
||||
'matplotlib.pyplot',
|
||||
'mock',
|
||||
'numpy',
|
||||
'oauthlib',
|
||||
'oauthlib.oauth1',
|
||||
'oauthlib.oauth1.rfc5849',
|
||||
'PIL',
|
||||
'pymongo',
|
||||
'pyparsing',
|
||||
'pysrt',
|
||||
'requests',
|
||||
'scipy.interpolate',
|
||||
'scipy.constants',
|
||||
'scipy.optimize',
|
||||
'yaml',
|
||||
'webob',
|
||||
'webob.multidict',
|
||||
]
|
||||
|
||||
if on_rtd:
|
||||
for mod_name in MOCK_MODULES:
|
||||
sys.modules[mod_name] = Mock()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# from http://djangosnippets.org/snippets/2533/
|
||||
# autogenerate models definitions
|
||||
|
||||
import inspect
|
||||
import types
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
|
||||
def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||
"""
|
||||
Similar to smart_unicode, except that lazy instances are resolved to
|
||||
strings, rather than kept as lazy objects.
|
||||
|
||||
If strings_only is True, don't convert (some) non-string-like objects.
|
||||
"""
|
||||
if strings_only and isinstance(s, (types.NoneType, int)):
|
||||
return s
|
||||
if not isinstance(s, basestring,):
|
||||
if hasattr(s, '__unicode__'):
|
||||
s = unicode(s)
|
||||
else:
|
||||
s = unicode(str(s), encoding, errors)
|
||||
elif not isinstance(s, unicode):
|
||||
s = unicode(s, encoding, errors)
|
||||
return s
|
||||
|
||||
|
||||
class MLStripper(HTMLParser):
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
self.fed = []
|
||||
|
||||
def handle_data(self, d):
|
||||
self.fed.append(d)
|
||||
|
||||
def get_data(self):
|
||||
return ''.join(self.fed)
|
||||
|
||||
|
||||
def strip_tags(html):
|
||||
s = MLStripper()
|
||||
s.feed(html)
|
||||
return s.get_data()
|
||||
|
||||
|
||||
def process_docstring(app, what, name, obj, options, lines):
|
||||
"""Autodoc django models"""
|
||||
|
||||
# This causes import errors if left outside the function
|
||||
from django.db import models
|
||||
|
||||
# If you want extract docs from django forms:
|
||||
# from django import forms
|
||||
# from django.forms.models import BaseInlineFormSet
|
||||
|
||||
# Only look at objects that inherit from Django's base MODEL class
|
||||
if inspect.isclass(obj) and issubclass(obj, models.Model):
|
||||
# Grab the field list from the meta class
|
||||
fields = obj._meta._fields()
|
||||
|
||||
for field in fields:
|
||||
# Decode and strip any html out of the field's help text
|
||||
help_text = strip_tags(force_unicode(field.help_text))
|
||||
|
||||
# Decode and capitalize the verbose name, for use if there isn't
|
||||
# any help text
|
||||
verbose_name = force_unicode(field.verbose_name).capitalize()
|
||||
|
||||
if help_text:
|
||||
# Add the model field to the end of the docstring as a param
|
||||
# using the help text as the description
|
||||
lines.append(u':param %s: %s' % (field.attname, help_text))
|
||||
else:
|
||||
# Add the model field to the end of the docstring as a param
|
||||
# using the verbose name as the description
|
||||
lines.append(u':param %s: %s' % (field.attname, verbose_name))
|
||||
|
||||
# Add the field's type to the docstring
|
||||
lines.append(u':type %s: %s' % (field.attname, type(field).__name__))
|
||||
return lines
|
||||
|
||||
|
||||
def setup(app):
|
||||
"""Setup docsting processors"""
|
||||
#Register the docstring processor with sphinx
|
||||
app.connect('autodoc-process-docstring', process_docstring)
|
||||
|
||||
@@ -171,4 +171,4 @@ Get the HTML for the course about page.
|
||||
</article>\n
|
||||
</section>\n
|
||||
</section>"
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ The following tasks and endpoints are currently supported.
|
||||
- /api/mobile/v0.5/users/{username}
|
||||
* - :ref:`Get course enrollments for about a user<Get a User's Course Enrollments>`
|
||||
- /api/mobile/v0.5/users/{username}/course_enrollments/
|
||||
* - :ref:`Get or change user status in a course<Get or Change User Status in a Course>`
|
||||
- /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
* - :ref:`Get a course About page<Get the Course About Page>`
|
||||
- /api/mobile/v0.5/course_info/{organization}/{course_number}/{course_run}/about
|
||||
* - :ref:`Get updates for a course<Get Course Updates>`
|
||||
|
||||
@@ -35,6 +35,9 @@ With the edX Platform API, you can:
|
||||
* Get :ref:`user details<Get User Details>` and :ref:`course enrollments<Get a
|
||||
User's Course Enrollments>` for a user.
|
||||
|
||||
* :ref:`Get or change user status in a course <Get or Change User Status in a
|
||||
Course>`
|
||||
|
||||
* Get :ref:`course information<Get the Course About Page>`, :ref:`updates<Get
|
||||
Course Updates>`, and :ref:`handouts<Get Course Handouts>` for courses the
|
||||
user is enrolled in.
|
||||
|
||||
@@ -8,6 +8,7 @@ This page describes how to use the mobile user API to:
|
||||
|
||||
* `Get User Details`_
|
||||
* `Get a User's Course Enrollments`_
|
||||
* `Get or Change User Status in a Course`_
|
||||
|
||||
.. _Get User Details:
|
||||
|
||||
@@ -28,7 +29,7 @@ Users are redirected to this endpoint after logging in.
|
||||
You can use the **course_enrollments** value in the response to get a list of
|
||||
courses the user is enrolled in.
|
||||
|
||||
**Example request**:
|
||||
**Example request**
|
||||
|
||||
``GET /api/mobile/v0.5/users/{username}``
|
||||
|
||||
@@ -165,4 +166,62 @@ Get information about the courses the currently logged in user is enrolled in.
|
||||
"start": "2013-02-05T05:00:00Z",
|
||||
"course_image": "/c4x/edX/DemoX/asset/images_course_image.jpg"
|
||||
}
|
||||
}
|
||||
|
||||
.. _Get or Change User Status in a Course:
|
||||
|
||||
**************************************
|
||||
Get or Change User Status in a Course
|
||||
**************************************
|
||||
|
||||
.. .. autoclass:: mobile_api.users.views.UserCourseStatus
|
||||
.. :members:
|
||||
|
||||
**Use Case**
|
||||
|
||||
Get or update the ID of the module that the specified user last visited in the
|
||||
specified course.
|
||||
|
||||
**Example request**
|
||||
|
||||
``GET /api/mobile/v0.5/users/{username}/course_status_info/{course_id}``
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
PATCH /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
body:
|
||||
last_visited_module_id={module_id}
|
||||
modification_date={date}
|
||||
|
||||
The modification_date is optional. If it is present, the update will
|
||||
only take effect if the modification_date is later than the
|
||||
modification_date saved on the server.
|
||||
|
||||
**Response Values**
|
||||
|
||||
* last_visited_module_id: The ID of the last module visited by the user in the
|
||||
course.
|
||||
|
||||
* last_visited_module_path: The ID of the modules in the path from the last
|
||||
visited module to the course module.
|
||||
|
||||
**Example Response**
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
HTTP 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Allow: GET, HEAD, OPTIONS
|
||||
|
||||
{
|
||||
"last_visited_module_id": "i4x://edX/DemoX/html/6018785795994726950614ce7d0f38c5",
|
||||
|
||||
"last_visited_module_path": [
|
||||
"i4x://edX/DemoX/html/6018785795994726950614ce7d0f38c5",
|
||||
"i4x://edX/DemoX/vertical/26d89b08f75d48829a63520ed8b0037d",
|
||||
"i4x://edX/DemoX/sequential/dbe8fc027bcb4fe9afb744d2e8415855",
|
||||
"i4x://edX/DemoX/chapter/social_integration",
|
||||
"i4x://edX/DemoX/course/Demo_Course"
|
||||
]
|
||||
}
|
||||
@@ -70,8 +70,29 @@ class UserDetail(generics.RetrieveAPIView):
|
||||
@mobile_view(is_user=True)
|
||||
class UserCourseStatus(views.APIView):
|
||||
"""
|
||||
Endpoints for getting and setting meta data
|
||||
about a user's status within a given course.
|
||||
**Use Case**
|
||||
|
||||
Get or update the ID of the module that the specified user last visited in the specified course.
|
||||
|
||||
**Example request**:
|
||||
|
||||
GET /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
|
||||
PATCH /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
|
||||
body:
|
||||
last_visited_module_id={module_id}
|
||||
modification_date={date}
|
||||
|
||||
The modification_date is optional. If it is present, the update will only take effect
|
||||
if the modification_date is later than the modification_date saved on the server.
|
||||
|
||||
**Response Values**
|
||||
|
||||
* last_visited_module_id: The ID of the last module visited by the user in the course.
|
||||
|
||||
* last_visited_module_path: The ID of the modules in the path from the
|
||||
last visited module to the course module.
|
||||
"""
|
||||
|
||||
http_method_names = ["get", "patch"]
|
||||
@@ -142,20 +163,7 @@ class UserCourseStatus(views.APIView):
|
||||
@mobile_course_access()
|
||||
def get(self, request, course, *args, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
**Use Case**
|
||||
|
||||
Get meta data about user's status within a specific course
|
||||
|
||||
**Example request**:
|
||||
|
||||
GET /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
|
||||
**Response Values**
|
||||
|
||||
* last_visited_module_id: The id of the last module visited by the user in the given course
|
||||
|
||||
* last_visited_module_path: The ids of the modules in the path from the last visited module
|
||||
to the course module
|
||||
Get the ID of the module that the specified user last visited in the specified course.
|
||||
"""
|
||||
|
||||
return self._get_course_info(request, course)
|
||||
@@ -163,24 +171,7 @@ class UserCourseStatus(views.APIView):
|
||||
@mobile_course_access()
|
||||
def patch(self, request, course, *args, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
**Use Case**
|
||||
|
||||
Update meta data about user's status within a specific course
|
||||
|
||||
**Example request**:
|
||||
|
||||
PATCH /api/mobile/v0.5/users/{username}/course_status_info/{course_id}
|
||||
body:
|
||||
last_visited_module_id={module_id}
|
||||
modification_date={date}
|
||||
|
||||
modification_date is optional. If it is present, the update will only take effect
|
||||
if modification_date is later than the modification_date saved on the server
|
||||
|
||||
**Response Values**
|
||||
|
||||
The same as doing a GET on this path
|
||||
|
||||
Update the ID of the module that the specified user last visited in the specified course.
|
||||
"""
|
||||
module_id = request.DATA.get("last_visited_module_id")
|
||||
modification_date_string = request.DATA.get("modification_date")
|
||||
|
||||
Reference in New Issue
Block a user