Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-val
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-val
Commits
08c100fa
Commit
08c100fa
authored
May 24, 2017
by
muhammad-ammar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
view to update auto generated images
parent
f5f6f36e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
142 additions
and
4 deletions
+142
-4
edxval/models.py
+11
-3
edxval/tests/test_views.py
+75
-0
edxval/urls.py
+5
-0
edxval/views.py
+51
-1
No files found.
edxval/models.py
View file @
08c100fa
...
...
@@ -253,7 +253,7 @@ class ListField(models.TextField):
if
len
(
value
)
>
LIST_MAX_ITEMS
:
raise
ValidationError
(
u'list must not contain more than {} items.'
.
format
(
LIST_MAX_ITEMS
))
if
all
(
isinstance
(
item
,
str
)
for
item
in
value
)
is
False
:
if
all
(
isinstance
(
item
,
basestring
)
for
item
in
value
)
is
False
:
raise
ValidationError
(
u'list must only contain strings.'
)
return
value
...
...
@@ -268,18 +268,21 @@ class VideoImage(TimeStampedModel):
generated_images
=
ListField
()
@classmethod
def
create_or_update
(
cls
,
course_video
,
file_name
,
image_data
=
None
):
def
create_or_update
(
cls
,
course_video
,
file_name
=
None
,
image_data
=
None
,
generated_images
=
None
):
"""
Create a VideoImage object for a CourseVideo.
NOTE: If `image_data` is None then `file_name` value will be used as it is, otherwise
a new file name is constructed based on uuid and extension from `file_name` value.
`image_data` will be None in case of course re-run and export.
`image_data` will be None in case of course re-run and export. `generated_images` list
contains names of images auto generated by VEDA. If an image is not already set then first
image name from `generated_images` list will be used.
Arguments:
course_video (CourseVideo): CourseVideo instance
file_name (str): File name of the image
image_data (InMemoryUploadedFile): Image data to be saved.
generated_images (list): auto generated image names
Returns:
Returns a tuple of (video_image, created).
...
...
@@ -305,6 +308,11 @@ class VideoImage(TimeStampedModel):
)
raise
else
:
if
generated_images
:
video_image
.
generated_images
=
generated_images
if
not
video_image
.
image
.
name
:
file_name
=
generated_images
[
0
]
video_image
.
image
.
name
=
file_name
video_image
.
save
()
...
...
edxval/tests/test_views.py
View file @
08c100fa
...
...
@@ -2,6 +2,8 @@
"""
Tests for Video Abstraction Layer views
"""
from
ddt
import
ddt
,
data
,
unpack
from
django.core.urlresolvers
import
reverse
from
rest_framework
import
status
...
...
@@ -794,3 +796,76 @@ class SubtitleDetailTest(APIAuthTestCase):
url
,
video_subtitles
,
format
=
'json'
)
self
.
assertEqual
(
self
.
client
.
get
(
video_subtitles
[
'content_url'
])
.
content
,
'{"start": "00:00:00"}'
)
@ddt
class
VideoImagesViewTest
(
APIAuthTestCase
):
"""
Tests VideoImage update requests.
"""
def
setUp
(
self
):
"""
Used for manually creating profile objects which EncodedVideos require.
"""
self
.
course_id
=
'test_course_id'
self
.
video
=
Video
.
objects
.
create
(
**
constants
.
VIDEO_DICT_FISH
)
self
.
course_video
=
CourseVideo
.
objects
.
create
(
video
=
self
.
video
,
course_id
=
self
.
course_id
)
super
(
VideoImagesViewTest
,
self
)
.
setUp
()
def
test_update_auto_generated_images
(
self
):
"""
Tests POSTing generated images successfully.
"""
generated_images
=
[
'video-images/a.png'
,
'video-images/b.png'
,
'video-images/c.png'
]
url
=
reverse
(
'update-video-images'
)
response
=
self
.
client
.
post
(
url
,
{
'course_id'
:
self
.
course_id
,
'generated_images'
:
generated_images
},
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
self
.
course_video
.
video_image
.
image
.
name
,
generated_images
[
0
])
self
.
assertEqual
(
self
.
course_video
.
video_image
.
generated_images
,
generated_images
)
# verify that if we post again then `VideoImage.image.name` should not be updated
# but `VideoImage.generated_images` should be updated with new names.
new_generated_images
=
[
'a.png'
,
'b.png'
,
'c.png'
]
response
=
self
.
client
.
post
(
url
,
{
'course_id'
:
self
.
course_id
,
'generated_images'
:
new_generated_images
},
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
self
.
course_video
.
video_image
.
image
.
name
,
generated_images
[
0
])
course_video
=
CourseVideo
.
objects
.
get
(
video
=
self
.
video
,
course_id
=
self
.
course_id
)
self
.
assertEqual
(
course_video
.
video_image
.
generated_images
,
new_generated_images
)
@data
(
{
'post_data'
:
{},
'message'
:
u'course_id and generated_images must be specified to update a video image.'
},
{
'post_data'
:
{
'course_id'
:
'does_not_exit_course'
,
'generated_images'
:
[]},
'message'
:
u'CourseVideo not found for course_id: does_not_exit_course'
},
{
'post_data'
:
{
'course_id'
:
'test_course_id'
,
'generated_images'
:
[
1
,
2
,
3
]},
'message'
:
"[u'list must only contain strings.']"
},
)
@unpack
def
test_update_error_responses
(
self
,
post_data
,
message
):
"""
Tests error responses occurred during POSTing.
"""
url
=
reverse
(
'update-video-images'
)
response
=
self
.
client
.
post
(
url
,
post_data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
)
self
.
assertEqual
(
response
.
data
[
'message'
],
message
)
edxval/urls.py
View file @
08c100fa
...
...
@@ -28,4 +28,9 @@ urlpatterns = patterns(
views
.
get_subtitle
,
name
=
"subtitle-content"
),
url
(
r'^videos/video-images/update/$'
,
views
.
VideoImagesView
.
as_view
(),
name
=
'update-video-images'
),
)
edxval/views.py
View file @
08c100fa
"""
Views file for django app edxval.
"""
from
rest_framework.views
import
APIView
from
rest_framework
import
generics
from
rest_framework.authentication
import
SessionAuthentication
from
rest_framework_oauth.authentication
import
OAuth2Authentication
from
rest_framework.permissions
import
DjangoModelPermissions
from
rest_framework.response
import
Response
from
rest_framework
import
status
from
django.http
import
HttpResponse
from
django.shortcuts
import
get_object_or_404
from
django.core.exceptions
import
ValidationError
from
django.views.decorators.http
import
last_modified
from
edxval.models
import
Video
,
Profile
,
Subtitle
from
edxval.models
import
Video
,
Profile
,
Subtitle
,
CourseVideo
,
VideoImage
from
edxval.serializers
import
(
VideoSerializer
,
SubtitleSerializer
...
...
@@ -99,6 +103,52 @@ class SubtitleDetail(MultipleFieldLookupMixin, generics.RetrieveUpdateDestroyAPI
serializer_class
=
SubtitleSerializer
class
VideoImagesView
(
APIView
):
"""
View to update course video images.
"""
authentication_classes
=
(
OAuth2Authentication
,
SessionAuthentication
)
def
post
(
self
,
request
):
"""
Update a course video image instance with auto generated image names.
"""
attrs
=
(
'course_id'
,
'generated_images'
)
missing
=
[
attr
for
attr
in
attrs
if
attr
not
in
request
.
data
]
if
missing
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
u'{missing} must be specified to update a video image.'
.
format
(
missing
=
' and '
.
join
(
missing
)
)
}
)
course_id
=
request
.
data
[
'course_id'
]
generated_images
=
request
.
data
[
'generated_images'
]
try
:
course_video
=
CourseVideo
.
objects
.
select_related
(
'video_image'
)
.
get
(
course_id
=
unicode
(
course_id
)
)
except
CourseVideo
.
DoesNotExist
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
u'CourseVideo not found for course_id: {course_id}'
.
format
(
course_id
=
course_id
)}
)
try
:
VideoImage
.
create_or_update
(
course_video
,
generated_images
=
generated_images
)
except
ValidationError
as
ex
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
str
(
ex
)}
)
return
Response
()
def
_last_modified_subtitle
(
request
,
edx_video_id
,
language
):
# pylint: disable=W0613
"""
Returns the last modified subtitle
...
...
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