Commit 595d4f28 by christopher lee

implemented correct identities for PUT

Assigned profile_name to be the identifier for EncodedVideos.
Tests for PUT have been added to check for expected behavior.
Attempting to PUT multiple EncodedVideos with the same profile
will return an error.

Other notes:
-url now accepts dashes
-reduced number of unique constants
-updated api.py tests with HTTP requests
-removed unused repr
parent e793792a
...@@ -13,26 +13,18 @@ class Profile(models.Model): ...@@ -13,26 +13,18 @@ class Profile(models.Model):
profile_name = models.CharField( profile_name = models.CharField(
max_length=50, max_length=50,
unique=True, unique=True,
) )
extension = models.CharField(max_length=10) extension = models.CharField(max_length=10)
width = models.PositiveIntegerField() width = models.PositiveIntegerField()
height = models.PositiveIntegerField() height = models.PositiveIntegerField()
def __repr__(self):
return (
u"Profile(profile_name={0.profile_name})"
).format(self)
def __unicode__(self):
return repr(self)
class Video(models.Model): class Video(models.Model):
""" """
Model for a Video group with the same content. Model for a Video group with the same content.
A video can have multiple formats. This model is the collection of those A video can have multiple formats. This model are the fields that represent
videos with fields that do not change across formats. the collection of those videos that do not change across formats.
""" """
edx_video_id = models.CharField( edx_video_id = models.CharField(
max_length=50, max_length=50,
...@@ -48,14 +40,6 @@ class Video(models.Model): ...@@ -48,14 +40,6 @@ class Video(models.Model):
client_video_id = models.CharField(max_length=255, db_index=True) client_video_id = models.CharField(max_length=255, db_index=True)
duration = models.FloatField(validators=[MinValueValidator(0)]) duration = models.FloatField(validators=[MinValueValidator(0)])
def __repr__(self):
return (
u"Video(client_video_id={0.client_video_id}, duration={0.duration})"
).format(self)
def __unicode__(self):
return repr(self)
class CourseVideos(models.Model): class CourseVideos(models.Model):
""" """
...@@ -83,12 +67,3 @@ class EncodedVideo(models.Model): ...@@ -83,12 +67,3 @@ class EncodedVideo(models.Model):
profile = models.ForeignKey(Profile, related_name="+") profile = models.ForeignKey(Profile, related_name="+")
video = models.ForeignKey(Video, related_name="encoded_videos") video = models.ForeignKey(Video, related_name="encoded_videos")
def __repr__(self):
return (
u"EncodedVideo(video={0.video.client_video_id}, "
u"profile={0.profile.profile_name})"
).format(self)
def __unicode__(self):
return repr(self)
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Serializers for Video Abstraction Layer Serializers for Video Abstraction Layer
""" """
from rest_framework import serializers from rest_framework import serializers
from django.core.exceptions import ValidationError
from edxval.models import Profile, Video, EncodedVideo from edxval.models import Profile, Video, EncodedVideo
...@@ -31,10 +32,44 @@ class EncodedVideoSerializer(serializers.ModelSerializer): ...@@ -31,10 +32,44 @@ class EncodedVideoSerializer(serializers.ModelSerializer):
"profile", "profile",
) )
def get_identity(self, data):
"""
This hook is required for bulk update.
We need to override the default, to use the slug as the identity.
"""
return data.get('profile', None)
class VideoSerializer(serializers.HyperlinkedModelSerializer): class VideoSerializer(serializers.HyperlinkedModelSerializer):
encoded_videos = EncodedVideoSerializer(many=True, allow_add_remove=True) encoded_videos = EncodedVideoSerializer(
many=True,
allow_add_remove=True
)
class Meta: class Meta:
model = Video model = Video
lookup_field = "edx_video_id" lookup_field = "edx_video_id"
def restore_fields(self, data, files):
"""
Converts a dictionary of data into a dictionary of deserialized fields. Also
checks if there are duplicate profile_name(s). If there is, the deserialization
is rejected.
"""
reverted_data = {}
if data is not None and not isinstance(data, dict):
self._errors['non_field_errors'] = ['Invalid data']
return None
profiles = [ev["profile"] for ev in data.get("encoded_videos", [])]
if len(profiles) != len(set(profiles)):
self._errors['non_field_errors'] = ['Invalid data: duplicate profiles']
for field_name, field in self.fields.items():
field.initialize(parent=self, field_name=field_name)
try:
field.field_from_native(data, files, field_name, reverted_data)
except ValidationError as err:
self._errors[field_name] = list(err.messages)
return reverted_data
...@@ -23,7 +23,6 @@ ENCODED_VIDEO_DICT_MOBILE = dict( ...@@ -23,7 +23,6 @@ ENCODED_VIDEO_DICT_MOBILE = dict(
file_size=4545, file_size=4545,
bitrate=6767, bitrate=6767,
) )
ENCODED_VIDEO_DICT_DESKTOP = dict( ENCODED_VIDEO_DICT_DESKTOP = dict(
url="http://www.meowmagic.com", url="http://www.meowmagic.com",
file_size=1212, file_size=1212,
...@@ -38,28 +37,27 @@ VIDEO_DICT_NEGATIVE_DURATION = dict( ...@@ -38,28 +37,27 @@ VIDEO_DICT_NEGATIVE_DURATION = dict(
edx_video_id="thisis12char-thisis7", edx_video_id="thisis12char-thisis7",
encoded_videos=[] encoded_videos=[]
) )
ENCODED_VIDEO_DICT_NEGATIVE_FILESIZE = dict(
url="http://www.meowmix.com",
file_size=-25556,
bitrate=9600,
)
ENCODED_VIDEO_DICT_NEGATIVE_BITRATE = dict(
url="http://www.meowmix.com",
file_size=25556,
bitrate=-9600,
)
VIDEO_DICT_BEE_INVALID = dict( VIDEO_DICT_BEE_INVALID = dict(
client_video_id="Barking Bee", client_video_id="Barking Bee",
duration=111.00, duration=111.00,
edx_video_id="wa/sps", edx_video_id="wa/sps",
) )
VIDEO_DICT_INVALID_ID = dict( VIDEO_DICT_INVALID_ID = dict(
client_video_id="SuperSloth", client_video_id="SuperSloth",
duration=42, duration=42,
edx_video_id="sloppy/sloth!!", edx_video_id="sloppy/sloth!!",
encoded_videos=[] encoded_videos=[]
) )
ENCODED_VIDEO_DICT_NEGATIVE_FILESIZE = dict(
url="http://www.meowmix.com",
file_size=-25556,
bitrate=9600,
)
ENCODED_VIDEO_DICT_NEGATIVE_BITRATE = dict(
url="http://www.meowmix.com",
file_size=25556,
bitrate=-9600,
)
""" """
Non-latin/invalid Non-latin/invalid
""" """
...@@ -87,30 +85,43 @@ Fish ...@@ -87,30 +85,43 @@ Fish
VIDEO_DICT_FISH = dict( VIDEO_DICT_FISH = dict(
client_video_id="Shallow Swordfish", client_video_id="Shallow Swordfish",
duration=122.00, duration=122.00,
edx_video_id="supersoaker" edx_video_id="super-soaker"
)
VIDEO_DICT_DIFFERENT_ID_FISH = dict(
client_video_id="Shallow Swordfish",
duration=122.00,
edx_video_id="medium-soaker"
) )
ENCODED_VIDEO_DICT_FISH_MOBILE = dict( ENCODED_VIDEO_DICT_FISH_MOBILE = dict(
url="https://www.swordsingers.com", url="https://www.swordsingers.com",
file_size=9000, file_size=9000,
bitrate=42, bitrate=42,
profile="mobile", profile="mobile",
) )
ENCODED_VIDEO_DICT_FISH_DESKTOP = dict( ENCODED_VIDEO_DICT_FISH_DESKTOP = dict(
url="https://www.swordsplints.com", url="https://www.swordsplints.com",
file_size=1234, file_size=1234,
bitrate=4222, bitrate=4222,
profile="desktop", profile="desktop",
) )
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE = dict(
url="https://www.fishfellow.com",
file_size=1,
bitrate=1,
profile="mobile",
)
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP = dict(
url="https://www.furryfish.com",
file_size=2,
bitrate=2,
profile="desktop",
)
ENCODED_VIDEO_DICT_FISH_INVALID_PROFILE = dict( ENCODED_VIDEO_DICT_FISH_INVALID_PROFILE = dict(
url="https://www.swordsplints.com", url="https://www.swordsplints.com",
file_size=1234, file_size=1234,
bitrate=4222, bitrate=4222,
profile=11, profile="bird"
) )
COMPLETE_SET_FISH = dict( COMPLETE_SET_FISH = dict(
encoded_videos=[ encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE, ENCODED_VIDEO_DICT_FISH_MOBILE,
...@@ -118,7 +129,40 @@ COMPLETE_SET_FISH = dict( ...@@ -118,7 +129,40 @@ COMPLETE_SET_FISH = dict(
], ],
**VIDEO_DICT_FISH **VIDEO_DICT_FISH
) )
COMPLETE_SET_TWO_MOBILE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE,
ENCODED_VIDEO_DICT_FISH_MOBILE
],
**VIDEO_DICT_FISH
)
COMPLETE_SET_UPDATE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE,
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP
],
**VIDEO_DICT_FISH
)
COMPLETE_SET_DIFFERENT_ID_UPDATE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE,
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP
],
**VIDEO_DICT_DIFFERENT_ID_FISH
)
COMPLETE_SET_FIRST_HALF_UPDATE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE,
ENCODED_VIDEO_DICT_FISH_DESKTOP
],
**VIDEO_DICT_FISH
)
COMPLETE_SET_UPDATE_ONLY_DESKTOP_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP
],
**VIDEO_DICT_FISH
)
COMPLETE_SET_INVALID_ENCODED_VIDEO_FISH = dict( COMPLETE_SET_INVALID_ENCODED_VIDEO_FISH = dict(
encoded_videos=[ encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE, ENCODED_VIDEO_DICT_FISH_MOBILE,
...@@ -126,7 +170,6 @@ COMPLETE_SET_INVALID_ENCODED_VIDEO_FISH = dict( ...@@ -126,7 +170,6 @@ COMPLETE_SET_INVALID_ENCODED_VIDEO_FISH = dict(
], ],
**VIDEO_DICT_FISH **VIDEO_DICT_FISH
) )
COMPLETE_SET_INVALID_VIDEO_FISH = dict( COMPLETE_SET_INVALID_VIDEO_FISH = dict(
client_video_id="Shallow Swordfish", client_video_id="Shallow Swordfish",
duration=122.00, duration=122.00,
...@@ -141,8 +184,6 @@ COMPLETE_SETS_ALL_INVALID = [ ...@@ -141,8 +184,6 @@ COMPLETE_SETS_ALL_INVALID = [
COMPLETE_SET_INVALID_VIDEO_FISH, COMPLETE_SET_INVALID_VIDEO_FISH,
COMPLETE_SET_INVALID_VIDEO_FISH COMPLETE_SET_INVALID_VIDEO_FISH
] ]
""" """
Star Star
""" """
...@@ -157,14 +198,24 @@ ENCODED_VIDEO_DICT_STAR = dict( ...@@ -157,14 +198,24 @@ ENCODED_VIDEO_DICT_STAR = dict(
bitrate=42, bitrate=42,
profile="mobile" profile="mobile"
) )
ENCODED_VIDEO_UPDATE_DICT_STAR = dict(
url="https://www.whatyouare.com",
file_size=9000,
bitrate=42,
profile="mobile"
)
COMPLETE_SET_STAR = dict( COMPLETE_SET_STAR = dict(
encoded_videos=[ encoded_videos=[
ENCODED_VIDEO_DICT_STAR ENCODED_VIDEO_DICT_STAR
], ],
**VIDEO_DICT_STAR **VIDEO_DICT_STAR
) )
COMPLETE_SET_UPDATE_STAR = dict(
encoded_videos=[
ENCODED_VIDEO_UPDATE_DICT_STAR
],
**VIDEO_DICT_STAR
)
COMPLETE_SET_NOT_A_LIST = dict( COMPLETE_SET_NOT_A_LIST = dict(
encoded_videos=dict( encoded_videos=dict(
url="https://www.howIwonder.com", url="https://www.howIwonder.com",
...@@ -174,7 +225,6 @@ COMPLETE_SET_NOT_A_LIST = dict( ...@@ -174,7 +225,6 @@ COMPLETE_SET_NOT_A_LIST = dict(
), ),
**VIDEO_DICT_STAR **VIDEO_DICT_STAR
) )
COMPLETE_SET_EXTRA_VIDEO_FIELD = dict( COMPLETE_SET_EXTRA_VIDEO_FIELD = dict(
encoded_videos=[ encoded_videos=[
dict( dict(
...@@ -188,12 +238,13 @@ COMPLETE_SET_EXTRA_VIDEO_FIELD = dict( ...@@ -188,12 +238,13 @@ COMPLETE_SET_EXTRA_VIDEO_FIELD = dict(
**VIDEO_DICT_STAR **VIDEO_DICT_STAR
) )
""" """
Unsorted Other
""" """
VIDEO_DICT_COAT = dict( VIDEO_DICT_ZEBRA = dict(
client_video_id="Callous Coat", client_video_id="Zesty Zebra",
duration=111.00, duration=111.00,
edx_video_id="itchyjacket" edx_video_id="zestttt",
encoded_videos=[]
) )
VIDEO_DICT_ANIMAL = dict( VIDEO_DICT_ANIMAL = dict(
client_video_id="Average Animal", client_video_id="Average Animal",
...@@ -201,48 +252,9 @@ VIDEO_DICT_ANIMAL = dict( ...@@ -201,48 +252,9 @@ VIDEO_DICT_ANIMAL = dict(
edx_video_id="mediocrity", edx_video_id="mediocrity",
encoded_videos=[] encoded_videos=[]
) )
VIDEO_DICT_ZEBRA = dict(
client_video_id="Zesty Zebra",
duration=111.00,
edx_video_id="zestttt",
encoded_videos=[]
)
VIDEO_DICT_UPDATE_ANIMAL = dict( VIDEO_DICT_UPDATE_ANIMAL = dict(
client_video_id="Lolcat", client_video_id="Above Average Animal",
duration=122.00, duration=999.00,
edx_video_id="mediocrity", edx_video_id="mediocrity",
encoded_videos=[]
) )
VIDEO_DICT_CRAYFISH = dict(
client_video_id="Crazy Crayfish",
duration=111.00,
edx_video_id="craycray",
)
VIDEO_DICT_DUPLICATES = [
VIDEO_DICT_CRAYFISH,
VIDEO_DICT_CRAYFISH,
VIDEO_DICT_CRAYFISH
]
COMPLETE_SETS = [
COMPLETE_SET_STAR,
COMPLETE_SET_FISH
]
COMPLETE_SETS_ONE_INVALID = [
COMPLETE_SET_STAR,
COMPLETE_SET_INVALID_VIDEO_FISH
]
VIDEO_DICT_SET_OF_THREE = [
VIDEO_DICT_COAT,
VIDEO_DICT_ANIMAL,
VIDEO_DICT_CRAYFISH
]
VIDEO_DICT_INVALID_SET = [
VIDEO_DICT_COAT,
VIDEO_DICT_INVALID_ID,
VIDEO_DICT_BEE_INVALID
]
...@@ -7,6 +7,9 @@ import mock ...@@ -7,6 +7,9 @@ import mock
from django.test import TestCase from django.test import TestCase
from django.db import DatabaseError from django.db import DatabaseError
from django.core.urlresolvers import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from edxval.models import Profile, Video, EncodedVideo from edxval.models import Profile, Video, EncodedVideo
from edxval import api as api from edxval import api as api
...@@ -16,26 +19,23 @@ from edxval.tests import constants ...@@ -16,26 +19,23 @@ from edxval.tests import constants
class GetVideoInfoTest(TestCase): class GetVideoInfoTest(TestCase):
#TODO When upload portion is finished, do not forget to create tests for validating
#TODO regex for models. Currently, objects are created manually and validators
#TODO are not triggered.
def setUp(self): def setUp(self):
""" """
Creates EncodedVideo objects in database Creates EncodedVideo objects in database
""" """
Profile.objects.create(**constants.PROFILE_DICT_MOBILE) Profile.objects.create(**constants.PROFILE_DICT_MOBILE)
Profile.objects.create(**constants.PROFILE_DICT_DESKTOP) Profile.objects.create(**constants.PROFILE_DICT_DESKTOP)
Video.objects.create(**constants.VIDEO_DICT_COAT) Video.objects.create(**constants.VIDEO_DICT_FISH)
EncodedVideo.objects.create( EncodedVideo.objects.create(
video=Video.objects.get( video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_COAT.get("edx_video_id") edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
), ),
profile=Profile.objects.get(profile_name="mobile"), profile=Profile.objects.get(profile_name="mobile"),
**constants.ENCODED_VIDEO_DICT_MOBILE **constants.ENCODED_VIDEO_DICT_MOBILE
) )
EncodedVideo.objects.create( EncodedVideo.objects.create(
video=Video.objects.get( video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_COAT.get("edx_video_id") edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
), ),
profile=Profile.objects.get(profile_name="desktop"), profile=Profile.objects.get(profile_name="desktop"),
**constants.ENCODED_VIDEO_DICT_DESKTOP **constants.ENCODED_VIDEO_DICT_DESKTOP
...@@ -45,7 +45,9 @@ class GetVideoInfoTest(TestCase): ...@@ -45,7 +45,9 @@ class GetVideoInfoTest(TestCase):
""" """
Tests for successful video request Tests for successful video request
""" """
self.assertIsNotNone(api.get_video_info(constants.EDX_VIDEO_ID)) self.assertIsNotNone(api.get_video_info(
constants.VIDEO_DICT_FISH.get("edx_video_id"))
)
def test_no_such_video(self): def test_no_such_video(self):
""" """
...@@ -71,7 +73,9 @@ class GetVideoInfoTest(TestCase): ...@@ -71,7 +73,9 @@ class GetVideoInfoTest(TestCase):
""" """
mock_init.side_effect = Exception("Mock error") mock_init.side_effect = Exception("Mock error")
with self.assertRaises(api.ValInternalError): with self.assertRaises(api.ValInternalError):
api.get_video_info(constants.EDX_VIDEO_ID) api.get_video_info(
constants.VIDEO_DICT_FISH.get("edx_video_id")
)
@mock.patch.object(Video.objects, 'get') @mock.patch.object(Video.objects, 'get')
def test_force_database_error(self, mock_get): def test_force_database_error(self, mock_get):
...@@ -80,4 +84,66 @@ class GetVideoInfoTest(TestCase): ...@@ -80,4 +84,66 @@ class GetVideoInfoTest(TestCase):
""" """
mock_get.side_effect = DatabaseError("DatabaseError") mock_get.side_effect = DatabaseError("DatabaseError")
with self.assertRaises(api.ValInternalError): with self.assertRaises(api.ValInternalError):
api.get_video_info(constants.EDX_VIDEO_ID) api.get_video_info(
constants.VIDEO_DICT_FISH.get("edx_video_id")
)
class GetVideoInfoTestWithHttpCalls(APITestCase):
def setUp(self):
"""
Creates EncodedVideo objects in database with HTTP requests.
The tests are similar to the GetVideoInfoTest class. This class
is to tests that we have the same results, using a populated
database via HTTP uploads.
"""
Profile.objects.create(**constants.PROFILE_DICT_MOBILE)
Profile.objects.create(**constants.PROFILE_DICT_DESKTOP)
url = reverse('video-list')
response = self.client.post(
url, constants.COMPLETE_SET_FISH, format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_get_video_found(self):
"""
Tests for successful video request
"""
self.assertIsNotNone(
api.get_video_info(
constants.COMPLETE_SET_FISH.get("edx_video_id")
)
)
def test_get_info_queries_for_two_encoded_video(self):
"""
Tests number of queries for a Video/EncodedVideo(1) pair
"""
with self.assertNumQueries(4):
api.get_video_info(constants.COMPLETE_SET_FISH.get("edx_video_id"))
def test_get_info_queries_for_one_encoded_video(self):
"""
Tests number of queries for a Video/EncodedVideo(1) pair
"""
url = reverse('video-list')
response = self.client.post(
url, constants.COMPLETE_SET_STAR, format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
with self.assertNumQueries(3):
api.get_video_info(constants.COMPLETE_SET_STAR.get("edx_video_id"))
def test_get_info_queries_for_only_video(self):
"""
Tests number of queries for a Video with no Encoded Videopair
"""
url = reverse('video-list')
response = self.client.post(
url, constants.VIDEO_DICT_ZEBRA, format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
with self.assertNumQueries(2):
api.get_video_info(constants.VIDEO_DICT_ZEBRA.get("edx_video_id"))
...@@ -63,13 +63,6 @@ class SerializerTests(TestCase): ...@@ -63,13 +63,6 @@ class SerializerTests(TestCase):
ProfileSerializer ProfileSerializer
) )
def test_non_latin_deserialization(self):
"""
Tests deserialization of non-latin data
"""
#TODO write a test for this when we understand what we want
pass
def test_invalid_edx_video_id(self): def test_invalid_edx_video_id(self):
""" """
Test the Video model regex validation for edx_video_id field Test the Video model regex validation for edx_video_id field
...@@ -84,7 +77,7 @@ class SerializerTests(TestCase): ...@@ -84,7 +77,7 @@ class SerializerTests(TestCase):
""" """
Tests for basic structure of EncodedVideoSetSerializer Tests for basic structure of EncodedVideoSetSerializer
""" """
video = Video.objects.create(**constants.VIDEO_DICT_COAT) video = Video.objects.create(**constants.VIDEO_DICT_FISH)
EncodedVideo.objects.create( EncodedVideo.objects.create(
video=video, video=video,
profile=Profile.objects.get(profile_name="desktop"), profile=Profile.objects.get(profile_name="desktop"),
...@@ -99,4 +92,4 @@ class SerializerTests(TestCase): ...@@ -99,4 +92,4 @@ class SerializerTests(TestCase):
# Check for 2 EncodedVideo entries # Check for 2 EncodedVideo entries
self.assertEqual(len(result.get("encoded_videos")), 2) self.assertEqual(len(result.get("encoded_videos")), 2)
# Check for original Video data # Check for original Video data
self.assertDictContainsSubset(constants.VIDEO_DICT_COAT, result) self.assertDictContainsSubset(constants.VIDEO_DICT_FISH, result)
...@@ -9,7 +9,7 @@ admin.autodiscover() ...@@ -9,7 +9,7 @@ admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^edxval/video/$', views.VideoList.as_view(), url(r'^edxval/video/$', views.VideoList.as_view(),
name="video-list"), name="video-list"),
url(r'^edxval/video/(?P<edx_video_id>\w+)', url(r'^edxval/video/(?P<edx_video_id>[-\w]+)',
views.VideoDetail.as_view(), views.VideoDetail.as_view(),
name="video-detail"), name="video-detail"),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
......
from rest_framework import generics from rest_framework import generics
from edxval.models import Video from edxval.models import Video, Profile
from edxval.serializers import ( from edxval.serializers import (
VideoSerializer VideoSerializer,
ProfileSerializer
) )
...@@ -14,6 +15,14 @@ class VideoList(generics.ListCreateAPIView): ...@@ -14,6 +15,14 @@ class VideoList(generics.ListCreateAPIView):
lookup_field = "edx_video_id" lookup_field = "edx_video_id"
serializer_class = VideoSerializer serializer_class = VideoSerializer
class ProfileList(generics.ListCreateAPIView):
"""
GETs or POST video objects
"""
queryset = Profile.objects.all()
lookup_field = "profile_name"
serializer_class = ProfileSerializer
class VideoDetail(generics.RetrieveUpdateDestroyAPIView): class VideoDetail(generics.RetrieveUpdateDestroyAPIView):
""" """
......
from django.conf.urls import patterns, include, url from django.conf.urls import patterns, include, url
from rest_framework.urlpatterns import format_suffix_patterns
from edxval import views from edxval import views
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment