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
00b48e54
Commit
00b48e54
authored
Apr 01, 2016
by
Clinton Blackburn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Exposing absolute/CDN image URLs via Course API
ECOM-4013
parent
982e99bd
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
87 additions
and
2 deletions
+87
-2
lms/djangoapps/course_api/serializers.py
+15
-0
lms/djangoapps/course_api/tests/test_serializers.py
+8
-1
openedx/core/lib/api/fields.py
+23
-1
openedx/core/lib/api/tests/test_fields.py
+41
-0
No files found.
lms/djangoapps/course_api/serializers.py
View file @
00b48e54
...
...
@@ -8,12 +8,14 @@ from django.core.urlresolvers import reverse
from
rest_framework
import
serializers
from
openedx.core.djangoapps.models.course_details
import
CourseDetails
from
openedx.core.lib.api.fields
import
AbsoluteURLField
class
_MediaSerializer
(
serializers
.
Serializer
):
# pylint: disable=abstract-method
"""
Nested serializer to represent a media object.
"""
def
__init__
(
self
,
uri_attribute
,
*
args
,
**
kwargs
):
super
(
_MediaSerializer
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
uri_attribute
=
uri_attribute
...
...
@@ -27,12 +29,25 @@ class _MediaSerializer(serializers.Serializer): # pylint: disable=abstract-meth
return
getattr
(
course_overview
,
self
.
uri_attribute
)
class
ImageSerializer
(
serializers
.
Serializer
):
# pylint: disable=abstract-method
"""
Collection of URLs pointing to images of various sizes.
The URLs will be absolute URLs with the host set to the host of the current request. If the values to be
serialized are already absolute URLs, they will be unchanged.
"""
raw
=
AbsoluteURLField
()
small
=
AbsoluteURLField
()
large
=
AbsoluteURLField
()
class
_CourseApiMediaCollectionSerializer
(
serializers
.
Serializer
):
# pylint: disable=abstract-method
"""
Nested serializer to represent a collection of media objects
"""
course_image
=
_MediaSerializer
(
source
=
'*'
,
uri_attribute
=
'course_image_url'
)
course_video
=
_MediaSerializer
(
source
=
'*'
,
uri_attribute
=
'course_video_url'
)
image
=
ImageSerializer
(
source
=
'image_urls'
)
class
CourseSerializer
(
serializers
.
Serializer
):
# pylint: disable=abstract-method
...
...
lms/djangoapps/course_api/tests/test_serializers.py
View file @
00b48e54
...
...
@@ -35,6 +35,8 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
self
.
honor_user
=
self
.
create_user
(
'honor'
,
is_staff
=
False
)
self
.
request_factory
=
APIRequestFactory
()
image_path
=
u'/c4x/edX/toy/asset/just_a_test.jpg'
image_url
=
u'http://testserver'
+
image_path
self
.
expected_data
=
{
'id'
:
u'edX/toy/2012_Fall'
,
'name'
:
u'Toy Course'
,
...
...
@@ -43,10 +45,15 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
'short_description'
:
u'A course about toys.'
,
'media'
:
{
'course_image'
:
{
'uri'
:
u'/c4x/edX/toy/asset/just_a_test.jpg'
,
'uri'
:
image_path
,
},
'course_video'
:
{
'uri'
:
u'http://www.youtube.com/watch?v=test_youtube_id'
,
},
'image'
:
{
'raw'
:
image_url
,
'small'
:
image_url
,
'large'
:
image_url
,
}
},
'start'
:
u'2015-07-17T12:00:00Z'
,
...
...
openedx/core/lib/api/fields.py
View file @
00b48e54
"""Fields useful for edX API implementations."""
from
rest_framework.serializers
import
Field
from
rest_framework.serializers
import
Field
,
URLField
class
ExpandableField
(
Field
):
...
...
@@ -9,6 +9,7 @@ class ExpandableField(Field):
collapsed_serializer (Serializer): the serializer to use for a non-expanded representation.
expanded_serializer (Serializer): the serializer to use for an expanded representation.
"""
def
__init__
(
self
,
**
kwargs
):
"""Sets up the ExpandableField with the collapsed and expanded versions of the serializer."""
assert
'collapsed_serializer'
in
kwargs
and
'expanded_serializer'
in
kwargs
...
...
@@ -32,3 +33,24 @@ class ExpandableField(Field):
self
.
expanded
.
context
[
"expand"
]
=
set
(
field
.
context
.
get
(
"expand"
,
[]))
return
field
.
to_representation
(
obj
)
class
AbsoluteURLField
(
URLField
):
"""
Field that serializes values to absolute URLs based on the current request.
If the value to be serialized is already a URL, that value will returned.
"""
def
to_representation
(
self
,
value
):
request
=
self
.
context
.
get
(
'request'
,
None
)
assert
request
is
not
None
,
(
"`
%
s` requires the request in the serializer context. "
"Add `context={'request': request}` when instantiating the serializer."
%
self
.
__class__
.
__name__
)
if
value
.
startswith
((
'http:'
,
'https:'
)):
return
value
return
request
.
build_absolute_uri
(
value
)
openedx/core/lib/api/tests/test_fields.py
0 → 100644
View file @
00b48e54
""" Tests for custom DRF fields. """
import
ddt
from
django.test
import
TestCase
from
openedx.core.lib.api.fields
import
AbsoluteURLField
class
MockRequest
(
object
):
""" Mock request object. """
ROOT
=
'http://example.com'
def
build_absolute_uri
(
self
,
value
):
""" Mocks `Request.build_absolute_uri`. """
return
self
.
ROOT
+
value
@ddt.ddt
class
AbsoluteURLFieldTests
(
TestCase
):
""" Tests for the AbsoluteURLField. """
def
setUp
(
self
):
super
(
AbsoluteURLFieldTests
,
self
)
.
setUp
()
self
.
field
=
AbsoluteURLField
()
self
.
field
.
_context
=
{
'request'
:
MockRequest
()}
# pylint:disable=protected-access
def
test_to_representation_without_request
(
self
):
""" Verify an AssertionError is raised if no request is passed as context to the field. """
self
.
field
.
_context
=
{}
# pylint:disable=protected-access
self
.
assertRaises
(
AssertionError
,
self
.
field
.
to_representation
,
'/image.jpg'
)
@ddt.data
(
'http://example.com'
,
'https://example.org'
)
def
test_to_representation_with_absolute_url
(
self
,
value
):
""" Verify the method returns the passed value, if the value is an absolute URL. """
self
.
assertEqual
(
self
.
field
.
to_representation
(
value
),
value
)
def
test_to_representation
(
self
):
""" Verify the method returns an absolute URL. """
self
.
assertEqual
(
self
.
field
.
to_representation
(
'/image.jpg'
),
MockRequest
.
ROOT
+
'/image.jpg'
)
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