views.py 7.66 KB
Newer Older
Nimisha Asthagiri committed
1 2 3 4
"""
Course API Views
"""

5
from django.core.exceptions import ValidationError
6
from rest_framework.generics import ListAPIView, RetrieveAPIView
7

8
from openedx.core.lib.api.paginators import NamespacedPageNumberPagination
9 10
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes

11
from .api import course_detail, list_courses
12
from .forms import CourseDetailGetForm, CourseListGetForm
13
from .serializers import CourseDetailSerializer, CourseSerializer
Nimisha Asthagiri committed
14 15


16 17
@view_auth_classes(is_authenticated=False)
class CourseDetailView(DeveloperErrorViewMixin, RetrieveAPIView):
Nimisha Asthagiri committed
18
    """
19 20
    **Use Cases**

21
        Request details for a course
22 23 24 25 26 27 28 29 30

    **Example Requests**

        GET /api/courses/v1/courses/{course_key}/

    **Response Values**

        Body consists of the following fields:

31 32
        * effort: A textual description of the weekly hours of effort expected
            in the course.
33 34 35
        * end: Date the course ends, in ISO 8601 notation
        * enrollment_end: Date enrollment ends, in ISO 8601 notation
        * enrollment_start: Date enrollment begins, in ISO 8601 notation
36 37
        * id: A unique identifier of the course; a serialized representation
            of the opaque key identifying the course.
38 39 40 41 42 43 44
        * media: An object that contains named media items.  Included here:
            * course_image: An image to show for the course.  Represented
              as an object with the following fields:
                * uri: The location of the image
        * name: Name of the course
        * number: Catalog number of the course
        * org: Name of the organization that owns the course
45 46 47
        * overview: A possibly verbose HTML textual description of the course.
            Note: this field is only included in the Course Detail view, not
            the Course List view.
48
        * short_description: A textual description of the course
49
        * start: Date the course begins, in ISO 8601 notation
50 51
        * start_display: Readably formatted start of the course
        * start_type: Hint describing how `start_display` is set. One of:
52 53 54
            * `"string"`: manually set by the course author
            * `"timestamp"`: generated from the `start` timestamp
            * `"empty"`: no start date is specified
55
        * pacing: Course pacing. Possible values: instructor, self
56

57 58
        Deprecated fields:

59
        * blocks_url: Used to fetch the course blocks
60 61
        * course_id: Course key (use 'id' instead)

62 63 64
    **Parameters:**

        username (optional):
65 66 67
            The username of the specified user for whom the course data
            is being accessed. The username is not only required if the API is
            requested by an Anonymous user.
68 69 70 71

    **Returns**

        * 200 on success with above fields.
72 73
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
        * 403 if a user who does not have permission to masquerade as
          another user specifies a username other than their own.
        * 404 if the course is not available or cannot be seen.

        Example response:

            {
                "blocks_url": "/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall",
                "media": {
                    "course_image": {
                        "uri": "/c4x/edX/example/asset/just_a_test.jpg",
                        "name": "Course Image"
                    }
                },
                "description": "An example course.",
                "end": "2015-09-19T18:00:00Z",
                "enrollment_end": "2015-07-15T00:00:00Z",
                "enrollment_start": "2015-06-15T00:00:00Z",
92
                "course_id": "edX/example/2012_Fall",
93 94 95
                "name": "Example Course",
                "number": "example",
                "org": "edX",
96
                "overview: "<p>A verbose description of the course.</p>"
97 98
                "start": "2015-07-17T12:00:00Z",
                "start_display": "July 17, 2015",
99 100
                "start_type": "timestamp",
                "pacing": "instructor"
101
            }
Nimisha Asthagiri committed
102 103
    """

104
    serializer_class = CourseDetailSerializer
105 106

    def get_object(self):
Nimisha Asthagiri committed
107
        """
108 109
        Return the requested course object, if the user has appropriate
        permissions.
110
        """
111 112 113 114 115
        requested_params = self.request.query_params.copy()
        requested_params.update({'course_key': self.kwargs['course_key_string']})
        form = CourseDetailGetForm(requested_params, initial={'requesting_user': self.request.user})
        if not form.is_valid():
            raise ValidationError(form.errors)
Nimisha Asthagiri committed
116

117 118 119 120 121
        return course_detail(
            self.request,
            form.cleaned_data['username'],
            form.cleaned_data['course_key'],
        )
122

Nimisha Asthagiri committed
123

124 125
@view_auth_classes(is_authenticated=False)
class CourseListView(DeveloperErrorViewMixin, ListAPIView):
126 127
    """
    **Use Cases**
Nimisha Asthagiri committed
128

129
        Request information on all courses visible to the specified user.
Nimisha Asthagiri committed
130

131
    **Example Requests**
Nimisha Asthagiri committed
132

133
        GET /api/courses/v1/courses/
Nimisha Asthagiri committed
134

135 136 137 138 139 140 141 142
    **Response Values**

        Body comprises a list of objects as returned by `CourseDetailView`.

    **Parameters**

        username (optional):
            The username of the specified user whose visible courses we
143 144
            want to see. The username is not required only if the API is
            requested by an Anonymous user.
Nimisha Asthagiri committed
145

146 147
        org (optional):
            If specified, visible `CourseOverview` objects are filtered
148 149 150 151 152 153 154
            such that only those belonging to the organization with the
            provided org code (e.g., "HarvardX") are returned.
            Case-insensitive.

        mobile (optional):
            If specified, only visible `CourseOverview` objects that are
            designated as mobile_available are returned.
155

156
    **Returns**
Nimisha Asthagiri committed
157

158 159
        * 200 on success, with a list of course discovery objects as returned
          by `CourseDetailView`.
160 161
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        * 403 if a user who does not have permission to masquerade as
          another user specifies a username other than their own.
        * 404 if the specified user does not exist, or the requesting user does
          not have permission to view their courses.

        Example response:

            [
              {
                "blocks_url": "/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall",
                "media": {
                  "course_image": {
                    "uri": "/c4x/edX/example/asset/just_a_test.jpg",
                    "name": "Course Image"
                  }
                },
                "description": "An example course.",
                "end": "2015-09-19T18:00:00Z",
                "enrollment_end": "2015-07-15T00:00:00Z",
                "enrollment_start": "2015-06-15T00:00:00Z",
182
                "course_id": "edX/example/2012_Fall",
183 184 185 186 187 188 189 190 191 192
                "name": "Example Course",
                "number": "example",
                "org": "edX",
                "start": "2015-07-17T12:00:00Z",
                "start_display": "July 17, 2015",
                "start_type": "timestamp"
              }
            ]
    """

193 194 195 196
    pagination_class = NamespacedPageNumberPagination
    serializer_class = CourseSerializer

    def get_queryset(self):
197
        """
198
        Return a list of courses visible to the user.
199
        """
200 201 202 203 204 205 206 207 208 209
        form = CourseListGetForm(self.request.query_params, initial={'requesting_user': self.request.user})
        if not form.is_valid():
            raise ValidationError(form.errors)

        return list_courses(
            self.request,
            form.cleaned_data['username'],
            org=form.cleaned_data['org'],
            filter_=form.cleaned_data['filter_'],
        )