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
5b1339b3
Commit
5b1339b3
authored
Aug 03, 2017
by
Qubad786
Committed by
muhammad-ammar
Aug 25, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add TranscriptPreference, prepare 3rd party transcription plans and their respective api methods
parent
ac5c5c23
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
510 additions
and
18 deletions
+510
-18
edxval/admin.py
+4
-1
edxval/api.py
+44
-4
edxval/migrations/0007_transcriptpreference.py
+35
-0
edxval/models.py
+102
-7
edxval/serializers.py
+28
-1
edxval/tests/constants.py
+22
-1
edxval/tests/test_api.py
+70
-1
edxval/tests/test_views.py
+45
-0
edxval/urls.py
+7
-2
edxval/utils.py
+98
-0
edxval/views.py
+55
-1
No files found.
edxval/admin.py
View file @
5b1339b3
...
...
@@ -3,7 +3,9 @@ Admin file for django app edxval.
"""
from
django.contrib
import
admin
from
.models
import
Video
,
Profile
,
EncodedVideo
,
VideoTranscript
,
CourseVideo
,
VideoImage
from
.models
import
(
CourseVideo
,
EncodedVideo
,
Profile
,
TranscriptPreference
,
Video
,
VideoImage
,
VideoTranscript
)
class
ProfileAdmin
(
admin
.
ModelAdmin
):
# pylint: disable=C0111
...
...
@@ -49,5 +51,6 @@ class CourseVideoAdmin(admin.ModelAdmin):
admin
.
site
.
register
(
Profile
,
ProfileAdmin
)
admin
.
site
.
register
(
Video
,
VideoAdmin
)
admin
.
site
.
register
(
VideoTranscript
)
admin
.
site
.
register
(
TranscriptPreference
)
admin
.
site
.
register
(
VideoImage
,
VideoImageAdmin
)
admin
.
site
.
register
(
CourseVideo
,
CourseVideoAdmin
)
edxval/api.py
View file @
5b1339b3
...
...
@@ -4,9 +4,9 @@
The internal API for VAL.
"""
import
logging
from
enum
import
Enum
from
django.core.exceptions
import
ObjectDoesNotExist
,
ValidationError
from
enum
import
Enum
from
lxml.etree
import
Element
,
SubElement
from
edxval.exceptions
import
(
InvalidTranscriptFormat
,
...
...
@@ -14,9 +14,11 @@ from edxval.exceptions import (InvalidTranscriptFormat,
ValCannotUpdateError
,
ValInternalError
,
ValVideoNotFoundError
)
from
edxval.models
import
(
CourseVideo
,
EncodedVideo
,
Profile
,
TranscriptFormat
,
TranscriptProviderType
,
Video
,
VideoImage
,
VideoTranscript
)
from
edxval.serializers
import
TranscriptSerializer
,
VideoSerializer
TranscriptFormat
,
TranscriptPreference
,
TranscriptProviderType
,
Video
,
VideoImage
,
VideoTranscript
)
from
edxval.serializers
import
TranscriptPreferenceSerializer
,
TranscriptSerializer
,
VideoSerializer
from
edxval.utils
import
THIRD_PARTY_TRANSCRIPTION_PLANS
logger
=
logging
.
getLogger
(
__name__
)
# pylint: disable=C0103
...
...
@@ -226,6 +228,44 @@ def create_or_update_video_transcript(
return
video_transcript
.
url
()
def
get_3rd_party_transcription_plans
():
"""
Retrieves 3rd party transcription plans.
"""
return
THIRD_PARTY_TRANSCRIPTION_PLANS
def
get_transcript_preferences
(
course_id
):
"""
Retrieves course wide transcript preferences
Arguments:
course_id (str): course id
"""
try
:
transcript_preference
=
TranscriptPreference
.
objects
.
get
(
course_id
=
course_id
)
except
TranscriptPreference
.
DoesNotExist
:
return
return
TranscriptPreferenceSerializer
(
transcript_preference
)
.
data
def
create_or_update_transcript_preferences
(
course_id
,
**
preferences
):
"""
Creates or updates course-wide transcript preferences
Arguments:
course_id(str): course id
Keyword Arguments:
preferences(dict): keyword arguments
"""
transcript_preference
,
__
=
TranscriptPreference
.
objects
.
update_or_create
(
course_id
=
course_id
,
defaults
=
preferences
)
return
TranscriptPreferenceSerializer
(
transcript_preference
)
.
data
def
get_course_video_image_url
(
course_id
,
edx_video_id
):
"""
Returns course video image url or None if no image found
...
...
edxval/migrations/0007_transcriptpreference.py
0 → 100644
View file @
5b1339b3
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-24 07:21
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.utils.timezone
import
edxval.models
import
model_utils.fields
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'edxval'
,
'0006_auto_20170823_0015'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'TranscriptPreference'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'created'
,
model_utils
.
fields
.
AutoCreatedField
(
default
=
django
.
utils
.
timezone
.
now
,
editable
=
False
,
verbose_name
=
'created'
)),
(
'modified'
,
model_utils
.
fields
.
AutoLastModifiedField
(
default
=
django
.
utils
.
timezone
.
now
,
editable
=
False
,
verbose_name
=
'modified'
)),
(
'course_id'
,
models
.
CharField
(
max_length
=
255
,
unique
=
True
,
verbose_name
=
b
'Course ID'
)),
(
'provider'
,
models
.
CharField
(
choices
=
[(
b
'Custom'
,
b
'Custom'
),
(
b
'3PlayMedia'
,
b
'3PlayMedia'
),
(
b
'Cielo24'
,
b
'Cielo24'
)],
max_length
=
20
,
verbose_name
=
b
'Provider'
)),
(
'cielo24_fidelity'
,
models
.
CharField
(
blank
=
True
,
choices
=
[(
b
'MECHANICAL'
,
b
'Mechanical, 75
%
Accuracy'
),
(
b
'PREMIUM'
,
b
'Premium, 95
%
Accuracy'
),
(
b
'PROFESSIONAL'
,
b
'Professional, 99
%
Accuracy'
)],
max_length
=
20
,
null
=
True
,
verbose_name
=
b
'Cielo24 Fidelity'
)),
(
'cielo24_turnaround'
,
models
.
CharField
(
blank
=
True
,
choices
=
[(
b
'STANDARD'
,
b
'Standard, 48h'
),
(
b
'PRIORITY'
,
b
'Priority, 24h'
)],
max_length
=
20
,
null
=
True
,
verbose_name
=
b
'Cielo24 Turnaround'
)),
(
'three_play_turnaround'
,
models
.
CharField
(
blank
=
True
,
choices
=
[(
b
'extended_service'
,
b
'10-Day/Extended'
),
(
b
'default'
,
b
'4-Day/Default'
),
(
b
'expedited_service'
,
b
'2-Day/Expedited'
),
(
b
'rush_service'
,
b
'24 hour/Rush'
),
(
b
'same_day_service'
,
b
'Same Day'
)],
max_length
=
20
,
null
=
True
,
verbose_name
=
b
'3PlayMedia Turnaround'
)),
(
'preferred_languages'
,
edxval
.
models
.
ListField
(
blank
=
True
,
default
=
[],
max_items
=
50
,
verbose_name
=
b
'Preferred Languages'
)),
],
options
=
{
'abstract'
:
False
,
},
),
]
edxval/models.py
View file @
5b1339b3
...
...
@@ -210,13 +210,17 @@ class ListField(models.TextField):
"""
ListField use to store and retrieve list data.
"""
def
__init__
(
self
,
max_items
=
LIST_MAX_ITEMS
,
*
args
,
**
kwargs
):
self
.
max_items
=
max_items
super
(
ListField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
get_prep_value
(
self
,
value
):
"""
Converts a list to its json represetation to store in database as text.
Converts a list to its json represe
n
tation to store in database as text.
"""
if
value
and
not
isinstance
(
value
,
list
):
raise
ValidationError
(
u'ListField value {} is not a list.'
.
format
(
value
))
return
json
.
dumps
(
self
.
validate
(
value
)
or
[])
return
json
.
dumps
(
self
.
validate
_list
(
value
)
or
[])
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
"""
...
...
@@ -233,7 +237,7 @@ class ListField(models.TextField):
# If a list is set then validated its items
if
isinstance
(
value
,
list
):
return
self
.
validate
(
value
)
py_list
=
self
.
validate_list
(
value
)
else
:
# try to de-serialize value and expect list and then validate
try
:
py_list
=
json
.
loads
(
value
)
...
...
@@ -241,13 +245,13 @@ class ListField(models.TextField):
if
not
isinstance
(
py_list
,
list
):
raise
TypeError
self
.
validate
(
py_list
)
self
.
validate
_list
(
py_list
)
except
(
ValueError
,
TypeError
):
raise
ValidationError
(
u'Must be a valid list of strings.'
)
return
py_list
def
validate
(
self
,
value
):
def
validate
_list
(
self
,
value
):
"""
Validate data before saving to database.
...
...
@@ -260,14 +264,23 @@ class ListField(models.TextField):
Raises:
ValidationError
"""
if
len
(
value
)
>
LIST_MAX_ITEMS
:
raise
ValidationError
(
u'list must not contain more than {} items.'
.
format
(
LIST_MAX_ITEMS
))
if
len
(
value
)
>
self
.
max_items
:
raise
ValidationError
(
u'list must not contain more than {max_items} items.'
.
format
(
max_items
=
self
.
max_items
)
)
if
all
(
isinstance
(
item
,
basestring
)
for
item
in
value
)
is
False
:
raise
ValidationError
(
u'list must only contain strings.'
)
return
value
def
deconstruct
(
self
):
name
,
path
,
args
,
kwargs
=
super
(
ListField
,
self
)
.
deconstruct
()
# Only include kwarg if it's not the default
if
self
.
max_items
!=
LIST_MAX_ITEMS
:
kwargs
[
'max_items'
]
=
self
.
max_items
return
name
,
path
,
args
,
kwargs
class
VideoImage
(
TimeStampedModel
):
"""
...
...
@@ -494,6 +507,88 @@ class Subtitle(models.Model):
return
'text/plain'
class
Cielo24Turnaround
(
object
):
"""
Cielo24 turnarounds.
"""
STANDARD
=
'STANDARD'
PRIORITY
=
'PRIORITY'
CHOICES
=
(
(
STANDARD
,
'Standard, 48h'
),
(
PRIORITY
,
'Priority, 24h'
),
)
class
Cielo24Fidelity
(
object
):
"""
Cielo24 fidelity.
"""
MECHANICAL
=
'MECHANICAL'
PREMIUM
=
'PREMIUM'
PROFESSIONAL
=
'PROFESSIONAL'
CHOICES
=
(
(
MECHANICAL
,
'Mechanical, 75
%
Accuracy'
),
(
PREMIUM
,
'Premium, 95
%
Accuracy'
),
(
PROFESSIONAL
,
'Professional, 99
%
Accuracy'
),
)
class
ThreePlayTurnaround
(
object
):
"""
3PlayMedia turnarounds.
"""
EXTENDED_SERVICE
=
'extended_service'
DEFAULT
=
'default'
EXPEDITED_SERVICE
=
'expedited_service'
RUSH_SERVICE
=
'rush_service'
SAME_DAY_SERVICE
=
'same_day_service'
CHOICES
=
(
(
EXTENDED_SERVICE
,
'10-Day/Extended'
),
(
DEFAULT
,
'4-Day/Default'
),
(
EXPEDITED_SERVICE
,
'2-Day/Expedited'
),
(
RUSH_SERVICE
,
'24 hour/Rush'
),
(
SAME_DAY_SERVICE
,
'Same Day'
),
)
class
TranscriptPreference
(
TimeStampedModel
):
"""
Third Party Transcript Preferences for a Course
"""
course_id
=
models
.
CharField
(
verbose_name
=
'Course ID'
,
max_length
=
255
,
unique
=
True
)
provider
=
models
.
CharField
(
verbose_name
=
'Provider'
,
max_length
=
20
,
choices
=
TranscriptProviderType
.
CHOICES
,
)
cielo24_fidelity
=
models
.
CharField
(
verbose_name
=
'Cielo24 Fidelity'
,
max_length
=
20
,
choices
=
Cielo24Fidelity
.
CHOICES
,
null
=
True
,
blank
=
True
,
)
cielo24_turnaround
=
models
.
CharField
(
verbose_name
=
'Cielo24 Turnaround'
,
max_length
=
20
,
choices
=
Cielo24Turnaround
.
CHOICES
,
null
=
True
,
blank
=
True
,
)
three_play_turnaround
=
models
.
CharField
(
verbose_name
=
'3PlayMedia Turnaround'
,
max_length
=
20
,
choices
=
ThreePlayTurnaround
.
CHOICES
,
null
=
True
,
blank
=
True
,
)
preferred_languages
=
ListField
(
verbose_name
=
'Preferred Languages'
,
max_items
=
50
,
default
=
[],
blank
=
True
)
def
__unicode__
(
self
):
return
u'{course_id} - {provider}'
.
format
(
course_id
=
self
.
course_id
,
provider
=
self
.
provider
)
@receiver
(
models
.
signals
.
post_save
,
sender
=
Video
)
def
video_status_update_callback
(
sender
,
**
kwargs
):
# pylint: disable=unused-argument
"""
...
...
edxval/serializers.py
View file @
5b1339b3
...
...
@@ -7,7 +7,7 @@ EncodedVideoSerializer which uses the profile_name as it's profile field.
from
rest_framework
import
serializers
from
rest_framework.fields
import
DateTimeField
,
IntegerField
from
edxval.models
import
(
CourseVideo
,
EncodedVideo
,
Profile
,
Video
,
from
edxval.models
import
(
CourseVideo
,
EncodedVideo
,
Profile
,
TranscriptPreference
,
Video
,
VideoImage
,
VideoTranscript
)
...
...
@@ -68,6 +68,7 @@ class TranscriptSerializer(serializers.ModelSerializer):
"""
return
transcript
.
url
()
class
CourseSerializer
(
serializers
.
RelatedField
):
"""
Field for CourseVideo
...
...
@@ -200,3 +201,29 @@ class VideoSerializer(serializers.ModelSerializer):
VideoImage
.
create_or_update
(
course_video
,
image_name
)
return
instance
class
TranscriptPreferenceSerializer
(
serializers
.
ModelSerializer
):
"""
Serializer for TranscriptPreference
"""
class
Meta
:
# pylint: disable=C1001, C0111
model
=
TranscriptPreference
fields
=
(
'course_id'
,
'provider'
,
'cielo24_fidelity'
,
'cielo24_turnaround'
,
'three_play_turnaround'
,
'preferred_languages'
,
'modified'
)
preferred_languages
=
serializers
.
SerializerMethodField
()
def
get_preferred_languages
(
self
,
transcript_preference
):
"""
Returns python list for preferred_languages model field.
"""
return
transcript_preference
.
preferred_languages
edxval/tests/constants.py
View file @
5b1339b3
...
...
@@ -3,7 +3,13 @@
"""
Constants used for tests.
"""
from
edxval.models
import
TranscriptFormat
,
TranscriptProviderType
from
edxval.models
import
(
TranscriptFormat
,
TranscriptProviderType
,
Cielo24Fidelity
,
Cielo24Turnaround
,
ThreePlayTurnaround
)
EDX_VIDEO_ID
=
"itchyjacket"
"""
...
...
@@ -406,3 +412,18 @@ VIDEO_TRANSCRIPT_3PLAY = dict(
provider
=
TranscriptProviderType
.
THREE_PLAY_MEDIA
,
file_format
=
TranscriptFormat
.
SJSON
,
)
TRANSCRIPT_PREFERENCES_CIELO24
=
dict
(
course_id
=
'edX/DemoX/Demo_Course'
,
provider
=
TranscriptProviderType
.
CIELO24
,
cielo24_fidelity
=
Cielo24Fidelity
.
PROFESSIONAL
,
cielo24_turnaround
=
Cielo24Turnaround
.
PRIORITY
,
preferred_languages
=
[
'ar'
]
)
TRANSCRIPT_PREFERENCES_3PLAY
=
dict
(
course_id
=
'edX/DemoX/Demo_Course'
,
provider
=
TranscriptProviderType
.
THREE_PLAY_MEDIA
,
three_play_turnaround
=
ThreePlayTurnaround
.
SAME_DAY_SERVICE
,
preferred_languages
=
[
'ar'
,
'en'
]
)
edxval/tests/test_api.py
View file @
5b1339b3
...
...
@@ -25,8 +25,9 @@ from edxval.api import (InvalidTranscriptFormat, InvalidTranscriptProvider,
VideoSortField
)
from
edxval.models
import
(
LIST_MAX_ITEMS
,
CourseVideo
,
EncodedVideo
,
Profile
,
TranscriptFormat
,
TranscriptProviderType
,
Video
,
VideoImage
,
VideoTranscript
)
VideoImage
,
VideoTranscript
,
TranscriptPreference
)
from
edxval.tests
import
APIAuthTestCase
,
constants
from
edxval
import
utils
FILE_DATA
=
"""
...
...
@@ -1684,3 +1685,71 @@ class TranscriptTest(TestCase):
File
(
open
(
existing_transcript_url
))
self
.
assertEqual
(
file_open_exception
.
exception
.
strerror
,
u'No such file or directory'
)
@ddt
class
TranscriptPreferencesTest
(
TestCase
):
"""
TranscriptPreferences API Tests
"""
def
setUp
(
self
):
"""
Tests setup
"""
self
.
course_id
=
'edX/DemoX/Demo_Course'
self
.
transcript_preferences
=
TranscriptPreference
.
objects
.
create
(
**
constants
.
TRANSCRIPT_PREFERENCES_CIELO24
)
self
.
prefs
=
dict
(
constants
.
TRANSCRIPT_PREFERENCES_CIELO24
)
self
.
prefs
.
update
(
constants
.
TRANSCRIPT_PREFERENCES_3PLAY
)
def
assert_prefs
(
self
,
received
,
expected
):
"""
Compare `received` with `expected` and assert if not equal
"""
# no need to compare modified datetime
del
received
[
'modified'
]
self
.
assertEqual
(
received
,
expected
)
def
test_get_3rd_party_transcription_plans
(
self
):
"""
Verify that `get_3rd_party_transcription_plans` api function works as expected
"""
self
.
assertEqual
(
api
.
get_3rd_party_transcription_plans
(),
utils
.
THIRD_PARTY_TRANSCRIPTION_PLANS
)
def
test_get_transcript_preferences
(
self
):
"""
Verify that `get_transcript_preferences` api function works as expected
"""
cielo24_prefs
=
dict
(
constants
.
TRANSCRIPT_PREFERENCES_CIELO24
)
cielo24_prefs
[
'three_play_turnaround'
]
=
None
transcript_preferences
=
api
.
get_transcript_preferences
(
self
.
course_id
)
self
.
assert_prefs
(
transcript_preferences
,
cielo24_prefs
)
def
test_update_transcript_preferences
(
self
):
"""
Verify that `create_or_update_transcript_preferences` api function updates as expected
"""
transcript_preferences
=
api
.
create_or_update_transcript_preferences
(
**
constants
.
TRANSCRIPT_PREFERENCES_3PLAY
)
self
.
assert_prefs
(
transcript_preferences
,
self
.
prefs
)
def
test_create_transcript_preferences
(
self
):
"""
Verify that `create_or_update_transcript_preferences` api function creates as expected
"""
self
.
prefs
[
'course_id'
]
=
'edX/DemoX/Astonomy'
# Verify that no preference is present for course id `edX/DemoX/Astonomy`
self
.
assertIsNone
(
api
.
get_transcript_preferences
(
self
.
prefs
[
'course_id'
]))
# create new preference
transcript_preferences
=
api
.
create_or_update_transcript_preferences
(
**
self
.
prefs
)
self
.
assert_prefs
(
transcript_preferences
,
self
.
prefs
)
# Verify that there should be 2 preferences exists
self
.
assertEqual
(
TranscriptPreference
.
objects
.
count
(),
2
)
edxval/tests/test_views.py
View file @
5b1339b3
...
...
@@ -990,3 +990,48 @@ class VideoTranscriptViewTest(APIAuthTestCase):
response
=
self
.
client
.
post
(
self
.
url
,
post_data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
)
self
.
assertEqual
(
response
.
data
[
'message'
],
message
)
@ddt
class
VideoStatusViewTest
(
APIAuthTestCase
):
"""
VideoStatusView Tests.
"""
def
setUp
(
self
):
"""
Tests setup.
"""
self
.
url
=
reverse
(
'video-status-update'
)
self
.
video
=
Video
.
objects
.
create
(
**
constants
.
VIDEO_DICT_FISH
)
super
(
VideoStatusViewTest
,
self
)
.
setUp
()
@data
(
{
'patch_data'
:
{},
'message'
:
u'"edx_video_id and status" params must be specified.'
,
'status_code'
:
status
.
HTTP_400_BAD_REQUEST
,
},
{
'patch_data'
:
{
'edx_video_id'
:
'super-soaker'
,
'status'
:
'fake'
},
'message'
:
u'"fake" is not a valid Video status.'
,
'status_code'
:
status
.
HTTP_400_BAD_REQUEST
,
},
{
'patch_data'
:
{
'edx_video_id'
:
'fake'
,
'status'
:
'transcription_ready'
},
'message'
:
u'Video is not found for specified edx_video_id: fake'
,
'status_code'
:
status
.
HTTP_400_BAD_REQUEST
,
},
{
'patch_data'
:
{
'edx_video_id'
:
'super-soaker'
,
'status'
:
'transcription_ready'
},
'message'
:
None
,
'status_code'
:
status
.
HTTP_200_OK
,
},
)
@unpack
def
test_transcript_status
(
self
,
patch_data
,
message
,
status_code
):
"""
Tests PATCHing video transcript status.
"""
response
=
self
.
client
.
patch
(
self
.
url
,
patch_data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
self
.
assertEqual
(
response
.
data
.
get
(
'message'
),
message
)
edxval/urls.py
View file @
5b1339b3
...
...
@@ -9,12 +9,17 @@ from edxval import views
urlpatterns
=
[
url
(
r'^videos/$'
,
views
.
VideoList
.
as_view
(),
name
=
"video-list"
name
=
'video-list'
),
url
(
r'^videos/(?P<edx_video_id>[-\w]+)$'
,
views
.
VideoDetail
.
as_view
(),
name
=
"video-detail"
name
=
'video-detail'
),
url
(
r'^videos/status/$'
,
views
.
VideoStatusView
.
as_view
(),
name
=
'video-status-update'
),
url
(
r'^videos/video-transcripts/create/$'
,
...
...
edxval/utils.py
View file @
5b1339b3
...
...
@@ -5,6 +5,104 @@ Util methods to be used in api and models.
from
django.conf
import
settings
from
django.core.files.storage
import
get_storage_class
# 3rd Party Transcription Plans
THIRD_PARTY_TRANSCRIPTION_PLANS
=
{
'Cielo24'
:
{
'display_name'
:
'Cielo24'
,
'turnaround'
:
{
'STANDARD'
:
'Standard, 48h'
,
'PRIORITY'
:
'Priority, 24h'
},
'fidelity'
:
{
'MECHANICAL'
:
{
'display_name'
:
'Mechanical, 75
%
Accuracy'
,
'languages'
:
{
'nl'
:
'Dutch'
,
'en'
:
'English'
,
'fr'
:
'French'
,
'de'
:
'German'
,
'it'
:
'Italian'
,
'es'
:
'Spanish'
,
}
},
'PREMIUM'
:
{
'display_name'
:
'Premium, 95
%
Accuracy'
,
'languages'
:
{
'en'
:
'English'
,
}
},
'PROFESSIONAL'
:
{
'display_name'
:
'Professional, 99
%
Accuracy'
,
'languages'
:
{
'ar'
:
'Arabic'
,
'zh-tw'
:
'Chinese - Mandarin (Traditional)'
,
'zh-cmn'
:
'Chinese - Mandarin (Simplified)'
,
'zh-yue'
:
'Chinese - Cantonese (Traditional)'
,
'nl'
:
'Dutch'
,
'en'
:
'English'
,
'fr'
:
'French'
,
'de'
:
'German'
,
'he'
:
'Hebrew'
,
'hi'
:
'Hindi'
,
'it'
:
'Italian'
,
'ja'
:
'Japanese'
,
'ko'
:
'Korean'
,
'pt'
:
'Portuguese'
,
'ru'
:
'Russian'
,
'es'
:
'Spanish'
,
'tr'
:
'Turkish'
,
}
},
}
},
'3PlayMedia'
:
{
'display_name'
:
'3PlayMedia'
,
'turnaround'
:
{
'extended_service'
:
'10-Day/Extended'
,
'default'
:
'4-Day/Default'
,
'expedited_service'
:
'2-Day/Expedited'
,
'rush_service'
:
'24-hour/Rush'
,
'same_day_service'
:
'Same Day'
},
'languages'
:
{
'en'
:
'English'
,
'fr'
:
'French'
,
'de'
:
'German'
,
'it'
:
'Italian'
,
'nl'
:
'Dutch'
,
'es-419'
:
'Spanish (Latin America)'
,
'pt'
:
'Portuguese'
,
'zh-hans'
:
'Chinese (Simplified)'
,
'zh-cmn-Hant'
:
'Chinese (Traditional)'
,
'ar'
:
'Arabic'
,
'he'
:
'Hebrew'
,
'ru'
:
'Russian'
,
'ja'
:
'Japanese'
,
'sv'
:
'Swedish'
,
'cs'
:
'Czech'
,
'da'
:
'Danish'
,
'fi'
:
'Finnish'
,
'id'
:
'Indonesian'
,
'ko'
:
'Korean'
,
'no'
:
'Norwegian'
,
'pl'
:
'Polish'
,
'th'
:
'Thai'
,
'tr'
:
'Turkish'
,
'vi'
:
'Vietnamese'
,
'ro'
:
'Romanian'
,
'hu'
:
'Hungarian'
,
'ms'
:
'Malay'
,
'bg'
:
'Bulgarian'
,
'tl'
:
'Tagalog'
,
'sr'
:
'Serbian'
,
'sk'
:
'Slovak'
,
'uk'
:
'Ukrainian'
,
}
}
}
def
video_image_path
(
video_image_instance
,
filename
):
# pylint:disable=unused-argument
"""
...
...
edxval/views.py
View file @
5b1339b3
...
...
@@ -14,7 +14,8 @@ from rest_framework.response import Response
from
rest_framework.views
import
APIView
from
rest_framework_oauth.authentication
import
OAuth2Authentication
from
edxval.api
import
create_or_update_video_transcript
,
get_video_transcript
,
create_or_update_video_transcript
from
edxval.api
import
(
create_or_update_video_transcript
,
get_video_transcript
,
update_video_status
)
from
edxval.models
import
(
CourseVideo
,
Profile
,
TranscriptFormat
,
TranscriptProviderType
,
Video
,
VideoImage
,
VideoTranscript
)
...
...
@@ -22,6 +23,11 @@ from edxval.serializers import TranscriptSerializer, VideoSerializer
LOGGER
=
logging
.
getLogger
(
__name__
)
# pylint: disable=C0103
VALID_VIDEO_STATUSES
=
[
'transcription_in_progress'
,
'transcription_ready'
,
]
class
ReadRestrictedDjangoModelPermissions
(
DjangoModelPermissions
):
"""Extending DjangoModelPermissions to allow us to restrict read access.
...
...
@@ -159,6 +165,54 @@ class VideoTranscriptView(APIView):
return
response
class
VideoStatusView
(
APIView
):
"""
A Video View to update the status of a video.
Note:
Currently, the valid statuses are `transcription_in_progress` and `transcription_ready` because it
was intended to only be used for video transcriptions but if you found it helpful to your needs, you
can add more statuses so that you can use it for updating other video statuses too.
"""
authentication_classes
=
(
OAuth2Authentication
,
SessionAuthentication
)
def
patch
(
self
,
request
):
"""
Update the status of a video.
"""
attrs
=
(
'edx_video_id'
,
'status'
)
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}" params must be specified.'
.
format
(
missing
=
' and '
.
join
(
missing
))}
)
edx_video_id
=
request
.
data
[
'edx_video_id'
]
video_status
=
request
.
data
[
'status'
]
if
video_status
not
in
VALID_VIDEO_STATUSES
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
u'"{status}" is not a valid Video status.'
.
format
(
status
=
video_status
)}
)
try
:
video
=
Video
.
objects
.
get
(
edx_video_id
=
edx_video_id
)
video
.
status
=
video_status
video
.
save
()
response_status
=
status
.
HTTP_200_OK
response_payload
=
{}
except
Video
.
DoesNotExist
:
response_status
=
status
.
HTTP_400_BAD_REQUEST
response_payload
=
{
'message'
:
u'Video is not found for specified edx_video_id: {edx_video_id}'
.
format
(
edx_video_id
=
edx_video_id
)
}
return
Response
(
status
=
response_status
,
data
=
response_payload
)
class
VideoImagesView
(
APIView
):
"""
View to update course video images.
...
...
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