Merge pull request #34977 from openedx/hajorg/au-2070-youtube-videos-id
feat: get youtube videos edx_video_id for a course
This commit is contained in:
@@ -42,6 +42,7 @@ from edxval.api import (
|
||||
update_video_status
|
||||
)
|
||||
from fs.osfs import OSFS
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from path import Path as path
|
||||
from pytz import UTC
|
||||
@@ -960,3 +961,32 @@ def _update_pagination_context(request):
|
||||
|
||||
request.session['VIDEOS_PER_PAGE'] = videos_per_page
|
||||
return JsonResponse()
|
||||
|
||||
|
||||
def get_course_youtube_edx_video_ids(course_id):
|
||||
"""
|
||||
Get a list of youtube edx_video_ids
|
||||
"""
|
||||
error_msg = "Invalid course_key: '%s'." % course_id
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
course = modulestore().get_course(course_key)
|
||||
except InvalidKeyError:
|
||||
return JsonResponse({'error': error_msg}, status=500)
|
||||
blocks = []
|
||||
block_yt_field = 'youtube_id_1_0'
|
||||
block_edx_id_field = 'edx_video_id'
|
||||
if hasattr(course, 'get_children'):
|
||||
for section in course.get_children():
|
||||
for subsection in section.get_children():
|
||||
for vertical in subsection.get_children():
|
||||
for block in vertical.get_children():
|
||||
blocks.append(block)
|
||||
|
||||
edx_video_ids = []
|
||||
for block in blocks:
|
||||
if hasattr(block, block_yt_field) and getattr(block, block_yt_field):
|
||||
if getattr(block, block_edx_id_field):
|
||||
edx_video_ids.append(getattr(block, block_edx_id_field))
|
||||
|
||||
return JsonResponse({'edx_video_ids': edx_video_ids}, status=200)
|
||||
|
||||
@@ -12,6 +12,7 @@ from io import StringIO
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import dateutil.parser
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
import ddt
|
||||
import pytz
|
||||
from django.test import TestCase
|
||||
@@ -37,6 +38,8 @@ from openedx.core.djangoapps.video_pipeline.config.waffle import (
|
||||
ENABLE_DEVSTACK_VIDEO_UPLOADS,
|
||||
)
|
||||
from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
from ..videos import (
|
||||
@@ -1662,3 +1665,82 @@ class GetStorageBucketTestCase(TestCase):
|
||||
|
||||
self.assertIn("https://vem_test_bucket.s3.amazonaws.com:443/test_root/", upload_url)
|
||||
self.assertIn(edx_video_id, upload_url)
|
||||
|
||||
|
||||
class CourseYoutubeEdxVideoIds(ModuleStoreTestCase):
|
||||
"""
|
||||
This test checks youtube videos in a course
|
||||
"""
|
||||
VIEW_NAME = 'youtube_edx_video_ids'
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.course_with_no_youtube_videos = CourseFactory.create()
|
||||
self.store = modulestore()
|
||||
self.user = UserFactory()
|
||||
self.client.login(username=self.user.username, password='Password1234')
|
||||
|
||||
def get_url_for_course_key(self, course_key, kwargs=None):
|
||||
"""Return video handler URL for the given course"""
|
||||
return reverse_course_url(self.VIEW_NAME, course_key, kwargs) # lint-amnesty, pylint: disable=no-member
|
||||
|
||||
def test_course_with_youtube_videos(self):
|
||||
course_key = self.course.id
|
||||
|
||||
with self.store.bulk_operations(course_key):
|
||||
chapter_loc = self.store.create_child(
|
||||
self.user.id, self.course.location, 'chapter', 'test_chapter'
|
||||
).location
|
||||
seq_loc = self.store.create_child(
|
||||
self.user.id, chapter_loc, 'sequential', 'test_seq'
|
||||
).location
|
||||
vert_loc = self.store.create_child(self.user.id, seq_loc, 'vertical', 'test_vert').location
|
||||
self.store.create_child(
|
||||
self.user.id,
|
||||
vert_loc,
|
||||
'problem',
|
||||
'test_problem',
|
||||
fields={"data": "<problem>Test</problem>"}
|
||||
)
|
||||
self.store.create_child(
|
||||
self.user.id, vert_loc, 'video', fields={
|
||||
"youtube_is_available": False,
|
||||
"name": "sample_video",
|
||||
"edx_video_id": "youtube_193_84709099",
|
||||
}
|
||||
)
|
||||
|
||||
response = self.client.get(self.get_url_for_course_key(course_key))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
edx_video_ids = json.loads(response.content.decode('utf-8'))['edx_video_ids']
|
||||
self.assertEqual(len(edx_video_ids), 1)
|
||||
|
||||
def test_course_with_no_youtube_videos(self):
|
||||
course_key = self.course_with_no_youtube_videos.id
|
||||
|
||||
with self.store.bulk_operations(course_key):
|
||||
chapter_loc = self.store.create_child(
|
||||
self.user.id, self.course_with_no_youtube_videos.location, 'chapter', 'test_chapter'
|
||||
).location
|
||||
seq_loc = self.store.create_child(
|
||||
self.user.id, chapter_loc, 'sequential', 'test_seq'
|
||||
).location
|
||||
vert_loc = self.store.create_child(self.user.id, seq_loc, 'vertical', 'test_vert').location
|
||||
self.store.create_child(
|
||||
self.user.id, vert_loc, 'problem', 'test_problem', fields={"data": "<problem>Test</problem>"}
|
||||
)
|
||||
self.store.create_child(
|
||||
self.user.id, vert_loc, 'video', fields={
|
||||
"youtube_id_1_0": None,
|
||||
"name": "sample_video",
|
||||
"edx_video_id": "no_youtube_193_84709099",
|
||||
}
|
||||
)
|
||||
|
||||
response = self.client.get(self.get_url_for_course_key(course_key))
|
||||
|
||||
edx_video_ids = json.loads(response.content.decode('utf-8'))['edx_video_ids']
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(edx_video_ids), 0)
|
||||
|
||||
@@ -27,6 +27,7 @@ from cms.djangoapps.contentstore.video_storage_handlers import (
|
||||
storage_service_key as storage_service_key_source_function,
|
||||
send_video_status_update as send_video_status_update_source_function,
|
||||
is_status_update_request as is_status_update_request_source_function,
|
||||
get_course_youtube_edx_video_ids,
|
||||
)
|
||||
|
||||
from common.djangoapps.util.json_request import expect_json
|
||||
@@ -41,6 +42,7 @@ __all__ = [
|
||||
'get_video_features',
|
||||
'transcript_preferences_handler',
|
||||
'generate_video_upload_link_handler',
|
||||
'get_course_youtube_edx_videos_ids',
|
||||
]
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
@@ -236,3 +238,18 @@ def is_status_update_request(request_data):
|
||||
Exposes helper method without breaking existing bindings/dependencies
|
||||
"""
|
||||
return is_status_update_request_source_function(request_data)
|
||||
|
||||
|
||||
@api_view(['GET'])
|
||||
@view_auth_classes()
|
||||
@require_GET
|
||||
def get_course_youtube_edx_videos_ids(request, course_key_string):
|
||||
"""
|
||||
Get an object containing course videos.
|
||||
**Example Request**
|
||||
GET /api/contentstore/v1/videos/youtube_ids{course_id}
|
||||
**Response Values**
|
||||
If the request is successful, an HTTP 200 "OK" response is returned.
|
||||
The HTTP 200 response contains a list of youtube edx_video_ids for a given course.
|
||||
"""
|
||||
return get_course_youtube_edx_video_ids(course_key_string)
|
||||
|
||||
@@ -194,6 +194,8 @@ urlpatterns = oauth2_urlpatterns + [
|
||||
path('api/val/v0/', include('edxval.urls')),
|
||||
path('api/tasks/v0/', include('user_tasks.urls')),
|
||||
path('accessibility', contentstore_views.accessibility, name='accessibility'),
|
||||
re_path(fr'api/youtube/courses/{COURSELIKE_KEY_PATTERN}/edx-video-ids$',
|
||||
contentstore_views.get_course_youtube_edx_videos_ids, name='youtube_edx_video_ids'),
|
||||
]
|
||||
|
||||
if not settings.DISABLE_DEPRECATED_SIGNIN_URL:
|
||||
|
||||
Reference in New Issue
Block a user