Commit d346e9a5 by Mushtaq Ali

Add video thumbnail to video model

parent 82d5a13c
...@@ -13,10 +13,18 @@ invalid profile_name will be returned. ...@@ -13,10 +13,18 @@ invalid profile_name will be returned.
import logging import logging
# from datetime import datetime
from django.conf import settings
from django.db import models from django.db import models
from django.dispatch import receiver from django.dispatch import receiver
from django.core.validators import MinValueValidator, RegexValidator from django.core.validators import MinValueValidator, RegexValidator
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.files.base import ContentFile
from django.core.files.storage import get_storage_class
from django.db import models, transaction
from django.utils.functional import cached_property
# from openedx.core.storage import get_storage
logger = logging.getLogger(__name__) # pylint: disable=C0103 logger = logging.getLogger(__name__) # pylint: disable=C0103
...@@ -72,6 +80,62 @@ class Profile(models.Model): ...@@ -72,6 +80,62 @@ class Profile(models.Model):
return self.profile_name return self.profile_name
def _create_path(directory, filename):
"""
Returns the full path for the given directory and filename.
"""
return '{}-{}'.format(directory, filename)
def _directory_name(edx_video_id):
"""
Returns the directory name for the given edx_video_id.
"""
return '{}{}'.format(settings.VIDEO_THUMBNAIL_SETTINGS.get('DIRECTORY_PREFIX', ''), edx_video_id)
def video_thumbnail_path_name(video_model, filename): # pylint:disable=unused-argument
"""
Returns path name to use for the given Video instance.
"""
return _create_path(_directory_name(video_model.edx_video_id), filename)
def get_video_thumbnail_storage():
"""
Return the configured django storage backend.
"""
return get_storage_class(
settings.VIDEO_THUMBNAIL_SETTINGS.get('STORAGE_CLASS'),
)(**settings.VIDEO_THUMBNAIL_SETTINGS.get('STORAGE_KWARGS', {}))
class CustomizableFileField(models.FileField):
"""
Subclass of FileField that allows custom settings to not
be serialized (hard-coded) in migrations. Otherwise,
migrations include optional settings for storage (such as
the storage class and bucket name); we don't want to
create new migration files for each configuration change.
"""
def __init__(self, *args, **kwargs):
kwargs.update(dict(
upload_to=video_thumbnail_path_name,
storage=get_video_thumbnail_storage(),
max_length=500, # allocate enough for filepath
blank=True,
null=True
))
super(CustomizableFileField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(CustomizableFileField, self).deconstruct()
del kwargs['upload_to']
del kwargs['storage']
del kwargs['max_length']
return name, path, args, kwargs
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.
...@@ -98,6 +162,18 @@ class Video(models.Model): ...@@ -98,6 +162,18 @@ class Video(models.Model):
client_video_id = models.CharField(max_length=255, db_index=True, blank=True) client_video_id = models.CharField(max_length=255, db_index=True, blank=True)
duration = models.FloatField(validators=[MinValueValidator(0)]) duration = models.FloatField(validators=[MinValueValidator(0)])
status = models.CharField(max_length=255, db_index=True) status = models.CharField(max_length=255, db_index=True)
thumbnail = CustomizableFileField()
# def thumbnail_url(self, name, edx_video_id=None):
# path = video_thumbnail_path_name(name, edx_video_id)
# return self._storage.url(path)
#
# @cached_property
# def _storage(self):
# """
# Return the configured django storage backend.
# """
# return get_video_thumbnail_storage()
def get_absolute_url(self): def get_absolute_url(self):
""" """
......
...@@ -130,6 +130,7 @@ INSTALLED_APPS = ( ...@@ -130,6 +130,7 @@ INSTALLED_APPS = (
# Third Party # Third Party
'django_nose', 'django_nose',
'rest_framework', 'rest_framework',
'storages',
# Our App # Our App
'edxval', 'edxval',
...@@ -178,3 +179,10 @@ LOGGING = { ...@@ -178,3 +179,10 @@ LOGGING = {
# copied from edx-platform # copied from edx-platform
COURSE_KEY_PATTERN = r'(?P<course_key_string>[^/+]+(/|\+)[^/+]+(/|\+)[^/]+)' COURSE_KEY_PATTERN = r'(?P<course_key_string>[^/+]+(/|\+)[^/+]+(/|\+)[^/]+)'
COURSE_ID_PATTERN = COURSE_KEY_PATTERN.replace('course_key_string', 'course_id') COURSE_ID_PATTERN = COURSE_KEY_PATTERN.replace('course_key_string', 'course_id')
VIDEO_THUMBNAIL_SETTINGS = dict(
# Backend storage
# STORAGE_CLASS='storages.backends.s3boto.S3BotoStorage',
# STORAGE_KWARGS=dict(bucket='mushi-mallow-bucket'),
DIRECTORY_PREFIX='videothumbnail/',
)
...@@ -56,8 +56,8 @@ class VideoList(generics.ListCreateAPIView): ...@@ -56,8 +56,8 @@ class VideoList(generics.ListCreateAPIView):
""" """
GETs or POST video objects GETs or POST video objects
""" """
authentication_classes = (OAuth2Authentication, SessionAuthentication) # authentication_classes = (OAuth2Authentication, SessionAuthentication)
permission_classes = (ReadRestrictedDjangoModelPermissions,) # permission_classes = (ReadRestrictedDjangoModelPermissions,)
queryset = Video.objects.all().prefetch_related("encoded_videos", "courses") queryset = Video.objects.all().prefetch_related("encoded_videos", "courses")
lookup_field = "edx_video_id" lookup_field = "edx_video_id"
serializer_class = VideoSerializer serializer_class = VideoSerializer
......
...@@ -4,3 +4,5 @@ enum34==1.0.4 ...@@ -4,3 +4,5 @@ enum34==1.0.4
lxml==3.3.6 lxml==3.3.6
-e git+https://github.com/edx/django-oauth2-provider.git@0.2.7-fork-edx-6a#egg=django-oauth2-provider==0.2.7-fork-edx-6 -e git+https://github.com/edx/django-oauth2-provider.git@0.2.7-fork-edx-6a#egg=django-oauth2-provider==0.2.7-fork-edx-6
-e git+https://github.com/edx/django-rest-framework-oauth.git@f0b503fda8c254a38f97fef802ded4f5fe367f7a#egg=djangorestframework-oauth -e git+https://github.com/edx/django-rest-framework-oauth.git@f0b503fda8c254a38f97fef802ded4f5fe367f7a#egg=djangorestframework-oauth
django-storages==1.5.2
boto==2.46.1
\ No newline at end of file
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