-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
Copy pathserializers.py
182 lines (153 loc) · 6.58 KB
/
serializers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
"""
Serializer for user API
"""
from rest_framework import serializers
from rest_framework.reverse import reverse
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.models import CourseEnrollment, User
from common.djangoapps.util.course import get_encoded_course_sharing_utm_params, get_link_for_about_page
from lms.djangoapps.certificates.api import certificate_downloadable_status
from lms.djangoapps.courseware.access import has_access
from openedx.features.course_duration_limits.access import get_user_course_expiration_date
class CourseOverviewField(serializers.RelatedField): # lint-amnesty, pylint: disable=abstract-method
"""
Custom field to wrap a CourseOverview object. Read-only.
"""
def to_representation(self, course_overview): # lint-amnesty, pylint: disable=arguments-differ
course_id = str(course_overview.id)
request = self.context.get('request')
api_version = self.context.get('api_version')
enrollment = CourseEnrollment.get_enrollment(user=self.context.get('request').user, course_key=course_id)
return {
# identifiers
'id': course_id,
'name': course_overview.display_name,
'number': course_overview.display_number_with_default,
'org': course_overview.display_org_with_default,
# dates
'start': course_overview.start,
'start_display': course_overview.start_display,
'start_type': course_overview.start_type,
'end': course_overview.end,
'dynamic_upgrade_deadline': enrollment.upgrade_deadline,
# notification info
'subscription_id': course_overview.clean_id(padding_char='_'),
# access info
'courseware_access': has_access(
request.user,
'load_mobile',
course_overview
).to_json(),
# various URLs
# course_image is sent in both new and old formats
# (within media to be compatible with the new Course API)
'media': {
'course_image': {
'uri': course_overview.course_image_url,
'name': 'Course Image',
}
},
'course_image': course_overview.course_image_url,
'course_about': get_link_for_about_page(course_overview),
'course_sharing_utm_parameters': get_encoded_course_sharing_utm_params(),
'course_updates': reverse(
'course-updates-list',
kwargs={'api_version': api_version, 'course_id': course_id},
request=request,
),
'course_handouts': reverse(
'course-handouts-list',
kwargs={'api_version': api_version, 'course_id': course_id},
request=request,
),
'discussion_url': reverse(
'discussion_course',
kwargs={'course_id': course_id},
request=request,
) if course_overview.is_discussion_tab_enabled() else None,
# This is an old API that was removed as part of DEPR-4. We keep the
# field present in case API parsers expect it, but this API is now
# removed.
'video_outline': None,
'is_self_paced': course_overview.self_paced
}
class CourseEnrollmentSerializer(serializers.ModelSerializer):
"""
Serializes CourseEnrollment models
"""
course = CourseOverviewField(source="course_overview", read_only=True)
certificate = serializers.SerializerMethodField()
audit_access_expires = serializers.SerializerMethodField()
course_modes = serializers.SerializerMethodField()
def get_audit_access_expires(self, model):
"""
Returns expiration date for a course audit expiration, if any or null
"""
return get_user_course_expiration_date(model.user, model.course)
def get_certificate(self, model):
"""Returns the information about the user's certificate in the course."""
certificate_info = certificate_downloadable_status(model.user, model.course_id)
if certificate_info['is_downloadable']:
return {
'url': self.context['request'].build_absolute_uri(
certificate_info['download_url']
),
}
else:
return {}
def get_course_modes(self, obj):
"""
Retrieve course modes associated with the course.
"""
course_modes = CourseMode.modes_for_course(
obj.course.id,
only_selectable=False
)
return [
ModeSerializer(mode).data
for mode in course_modes
]
class Meta:
model = CourseEnrollment
fields = ('audit_access_expires', 'created', 'mode', 'is_active', 'course', 'certificate', 'course_modes')
lookup_field = 'username'
class CourseEnrollmentSerializerv05(CourseEnrollmentSerializer):
"""
Serializes CourseEnrollment models for v0.5 api
Does not include 'audit_access_expires' field that is present in v1 api
"""
class Meta:
model = CourseEnrollment
fields = ('created', 'mode', 'is_active', 'course', 'certificate')
lookup_field = 'username'
class UserSerializer(serializers.ModelSerializer):
"""
Serializes User models
"""
name = serializers.ReadOnlyField(source='profile.name')
course_enrollments = serializers.SerializerMethodField()
def get_course_enrollments(self, model):
request = self.context.get('request')
api_version = self.context.get('api_version')
return reverse(
'courseenrollment-detail',
kwargs={'api_version': api_version, 'username': model.username},
request=request
)
class Meta:
model = User
fields = ('id', 'username', 'email', 'name', 'course_enrollments')
lookup_field = 'username'
# For disambiguating within the drf-yasg swagger schema
ref_name = 'mobile_api.User'
class ModeSerializer(serializers.Serializer): # pylint: disable=abstract-method
"""
Serializes a course's 'Mode' tuples
Returns a serialized representation of the modes available for course enrollment. The course
modes models are designed to return a tuple instead of the model object itself. This serializer
handles the given tuple.
"""
slug = serializers.CharField(max_length=100)
sku = serializers.CharField()
android_sku = serializers.CharField()
ios_sku = serializers.CharField()