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
from openedx.core.lib.api.view_utils import view_auth_classes, DeveloperErrorViewMixin
10
from .api import course_detail, list_courses
11
from .forms import CourseDetailGetForm, CourseListGetForm
12
from .serializers import CourseSerializer, CourseDetailSerializer
Nimisha Asthagiri committed
13 14


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

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

    **Example Requests**

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

    **Response Values**

        Body consists of the following fields:

30 31
        * effort: A textual description of the weekly hours of effort expected
            in the course.
32 33 34
        * 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
35 36
        * id: A unique identifier of the course; a serialized representation
            of the opaque key identifying the course.
37 38 39 40 41 42 43
        * 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
44 45 46
        * 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.
47
        * short_description: A textual description of the course
48
        * start: Date the course begins, in ISO 8601 notation
49 50
        * start_display: Readably formatted start of the course
        * start_type: Hint describing how `start_display` is set. One of:
51 52 53
            * `"string"`: manually set by the course author
            * `"timestamp"`: generated from the `start` timestamp
            * `"empty"`: no start date is specified
54
        * pacing: Course pacing. Possible values: instructor, self
55

56 57
        Deprecated fields:

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

61 62 63
    **Parameters:**

        username (optional):
64 65 66
            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.
67 68 69 70

    **Returns**

        * 200 on success with above fields.
71 72
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
        * 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",
91
                "course_id": "edX/example/2012_Fall",
92 93 94
                "name": "Example Course",
                "number": "example",
                "org": "edX",
95
                "overview: "<p>A verbose description of the course.</p>"
96 97
                "start": "2015-07-17T12:00:00Z",
                "start_display": "July 17, 2015",
98 99
                "start_type": "timestamp",
                "pacing": "instructor"
100
            }
Nimisha Asthagiri committed
101 102
    """

103
    serializer_class = CourseDetailSerializer
104 105

    def get_object(self):
Nimisha Asthagiri committed
106
        """
107 108
        Return the requested course object, if the user has appropriate
        permissions.
109
        """
110 111 112 113 114
        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
115

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

Nimisha Asthagiri committed
122

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

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

130
    **Example Requests**
Nimisha Asthagiri committed
131

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

134 135 136 137 138 139 140 141
    **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
142 143
            want to see. The username is not required only if the API is
            requested by an Anonymous user.
Nimisha Asthagiri committed
144

145 146
        org (optional):
            If specified, visible `CourseOverview` objects are filtered
147 148 149 150 151 152 153
            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.
154

155
    **Returns**
Nimisha Asthagiri committed
156

157 158
        * 200 on success, with a list of course discovery objects as returned
          by `CourseDetailView`.
159 160
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
        * 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",
181
                "course_id": "edX/example/2012_Fall",
182 183 184 185 186 187 188 189 190 191
                "name": "Example Course",
                "number": "example",
                "org": "edX",
                "start": "2015-07-17T12:00:00Z",
                "start_display": "July 17, 2015",
                "start_type": "timestamp"
              }
            ]
    """

192 193 194 195
    pagination_class = NamespacedPageNumberPagination
    serializer_class = CourseSerializer

    def get_queryset(self):
196
        """
197
        Return a list of courses visible to the user.
198
        """
199 200 201 202 203 204 205 206 207 208
        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_'],
        )