增加vod

This commit is contained in:
caoqianming 2022-03-26 23:34:27 +08:00
parent 93db656794
commit 9ba6f815e1
18 changed files with 345 additions and 1 deletions

View File

@ -0,0 +1,19 @@
# Generated by Django 3.0.4 on 2022-03-26 15:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('vod', '0001_initial'),
('examtest', '0032_auto_20210613_2234'),
]
operations = [
migrations.AddField(
model_name='workscope',
name='courses',
field=models.ManyToManyField(to='vod.Course', verbose_name='所选课程'),
),
]

View File

@ -3,6 +3,7 @@ from django.template.defaultfilters import default
from rbac.models import SoftCommonModel, CommonModel from rbac.models import SoftCommonModel, CommonModel
from django.contrib.postgres.fields import JSONField, ArrayField from django.contrib.postgres.fields import JSONField, ArrayField
from question.models import Questioncat, Question from question.models import Questioncat, Question
from vod.models import Course
@ -36,6 +37,7 @@ class WorkScope(CommonModel):
sortnum = models.IntegerField('排序码', default=1) sortnum = models.IntegerField('排序码', default=1)
is_public = models.BooleanField('是否公开', default=True) is_public = models.BooleanField('是否公开', default=True)
# can_choose = models.BooleanField('客户是否可选择', default=False) # can_choose = models.BooleanField('客户是否可选择', default=False)
courses = models.ManyToManyField(Course, verbose_name='所选课程')
class Meta: class Meta:
verbose_name = '工作类别' verbose_name = '工作类别'

View File

@ -6,6 +6,8 @@ from utils.custom import CommonPagination
from ..permission import RbacPermission from ..permission import RbacPermission
from ..models import Role from ..models import Role
from ..serializers.role_serializer import RoleListSerializer, RoleModifySerializer from ..serializers.role_serializer import RoleListSerializer, RoleModifySerializer
from rest_framework.response import Response
from rest_framework import status
class RoleViewSet(ModelViewSet): class RoleViewSet(ModelViewSet):

View File

@ -49,7 +49,8 @@ INSTALLED_APPS = [
'analyse', 'analyse',
'cms', 'cms',
'qtest', 'qtest',
'develop' 'develop',
'vod'
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@ -25,6 +25,7 @@ from utils.view import redirect
urlpatterns = [ urlpatterns = [
path('rbac/', include('rbac.urls')), path('rbac/', include('rbac.urls')),
path('vod/', include('vod.urls')),
path('develop/', include('develop.urls')), path('develop/', include('develop.urls')),
path('crm/', include('crm.urls')), path('crm/', include('crm.urls')),
path('question/', include('question.urls')), path('question/', include('question.urls')),

View File

@ -45,6 +45,7 @@ class FitJSONRenderer(JSONRenderer):
response = renderer_context.get("response") response = renderer_context.get("response")
response_body.code = response.status_code response_body.code = response.status_code
if response_body.code >= 400: # drf异常 if response_body.code >= 400: # drf异常
response_body.data = data
if isinstance(data, dict): if isinstance(data, dict):
data = data[list(data.keys())[0]] data = data[list(data.keys())[0]]
if isinstance(data, list): if isinstance(data, list):

View File

3
test_server/vod/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
test_server/vod/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class VodConfig(AppConfig):
name = 'vod'

View File

@ -0,0 +1,72 @@
# Generated by Django 3.0.4 on 2022-03-13 14:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Course',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('description', models.TextField(blank=True, null=True, verbose_name='课程介绍')),
('sort', models.IntegerField(default=1, verbose_name='排序数字')),
('create_admin', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_create_admin', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=100, verbose_name='视频名称')),
('description', models.TextField(blank=True, null=True, verbose_name='视频描述')),
('fileid', models.CharField(max_length=200, unique=True, verbose_name='云点播视频id')),
('mediaurl', models.CharField(max_length=200, verbose_name='视频地址')),
('coverurl', models.CharField(max_length=200, verbose_name='封面地址')),
('duration', models.IntegerField(default=0, verbose_name='时长(秒)')),
('views', models.IntegerField(default=0, verbose_name='观看次数')),
('viewsp', models.IntegerField(default=0, verbose_name='观看人数')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vod.Course', verbose_name='所属课程')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='VRecord',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('views', models.PositiveIntegerField(default=0, verbose_name='观看次数')),
('completed', models.BooleanField(default=False, verbose_name='是否观看完成')),
('current', models.PositiveIntegerField(default=0, verbose_name='当前观看进度(秒)')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='viewrecord_user', to=settings.AUTH_USER_MODEL, verbose_name='观看人')),
('video', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='record_video', to='vod.Video', verbose_name='点播视频')),
],
options={
'abstract': False,
},
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 3.0.4 on 2022-03-26 15:05
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('crm', '0040_auto_20220215_2120'),
('vod', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='vrecord',
name='user',
),
migrations.AddField(
model_name='vrecord',
name='consumer',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='viewrecord_consumer', to='crm.Consumer', verbose_name='观看人'),
preserve_default=False,
),
]

View File

37
test_server/vod/models.py Normal file
View File

@ -0,0 +1,37 @@
from django.db import models
from rbac.models import CommonModel, UserProfile
# Create your models here.
class Course(CommonModel):
"""
视频课程分类
"""
name = models.CharField(max_length=200, verbose_name='名称')
description = models.TextField(verbose_name='课程介绍', null=True, blank=True)
sort = models.IntegerField(default=1, verbose_name='排序数字')
create_admin = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=True, related_name='course_create_admin')
class Video(CommonModel):
"""
视频
"""
name = models.CharField(verbose_name='视频名称', max_length=100)
course = models.ForeignKey(Course, verbose_name='所属课程', on_delete=models.CASCADE)
description = models.TextField(verbose_name='视频描述', null=True, blank=True)
fileid = models.CharField(verbose_name='云点播视频id', unique=True, max_length=200)
mediaurl = models.CharField(verbose_name='视频地址', max_length=200)
coverurl = models.CharField(verbose_name='封面地址', max_length=200)
duration = models.IntegerField(verbose_name='时长(秒)', default=0)
views = models.IntegerField(verbose_name='观看次数', default=0)
viewsp = models.IntegerField(verbose_name='观看人数', default=0)
class VRecord(CommonModel):
"""
观看记录
"""
consumer = models.ForeignKey('crm.consumer', on_delete=models.CASCADE, verbose_name='观看人', related_name='viewrecord_consumer')
views = models.PositiveIntegerField(verbose_name='观看次数', default=0)
completed = models.BooleanField(verbose_name='是否观看完成', default=False)
current = models.PositiveIntegerField(verbose_name='当前观看进度(秒)', default=0)
video = models.ForeignKey(Video, verbose_name='点播视频', on_delete=models.CASCADE, related_name='record_video')

View File

@ -0,0 +1,14 @@
from rest_framework import serializers
from vod.models import Course, Video
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = '__all__'
class VideoSerializer(serializers.ModelSerializer):
course_name = serializers.CharField(source='course.name', read_only=True)
class Meta:
model = Video
fields = '__all__'

3
test_server/vod/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

13
test_server/vod/urls.py Normal file
View File

@ -0,0 +1,13 @@
from django.urls import path,include
from rest_framework import routers
from vod.views import CourseViewSet, VideoViewSet, SignatureAPIView
router = routers.DefaultRouter()
router.register('course', CourseViewSet, basename='course')
router.register('video', VideoViewSet, basename='video')
urlpatterns = [
path('signature/', SignatureAPIView.as_view()),
path('', include(router.urls)),
]

72
test_server/vod/views.py Normal file
View File

@ -0,0 +1,72 @@
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from rest_framework.views import APIView
from vod.models import Course, Video
from rest_framework.response import Response
from vod.serializers import CourseSerializer, VideoSerializer
from vod.vodclient import getSignature
from utils.custom import CommonPagination
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter, SearchFilter
from django.db.models import Q
# Create your views here.
class CourseViewSet(ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
ordering = ['id']
perms_map = [
{'get': '*'}, {'post': 'vod'},
{'put': 'vod'}, {'delete': 'vod'}]
def get_queryset(self):
queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset)
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(Q(create_admin = self.request.user)|Q(create_admin=self.request.user))
else:
return queryset.none()
return queryset
def perform_create(self, serializer):
serializer.save(create_admin=self.request.user)
def perform_update(self, serializer):
ret = serializer.validated_data
return super().perform_update(serializer)
class VideoViewSet(ModelViewSet):
queryset = Video.objects.all()
filterset_fields = ['course']
pagination_class = CommonPagination
serializer_class = VideoSerializer
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
ordering = ['-id']
perms_map = [
{'get': '*'}, {'post': 'vod'},
{'put': 'vod'}, {'delete': 'vod'}]
def get_queryset(self):
queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(course__create_admin = self.request.user)
else:
return queryset.none()
return queryset
class SignatureAPIView(APIView):
perms_map = [{'get': 'vod'}]
def get(self, request, format=None):
"""
获取上传签名
"""
signature = getSignature(procedure=request.query_params.get('procedure', None))
return Response({'signature':signature})

View File

@ -0,0 +1,73 @@
import base64
import hashlib
import hmac
import json
import random
import time
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import \
TencentCloudSDKException
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.vod.v20180717 import models, vod_client
SecretId = 'AKIDa8RTEiwsYw4uTlpc8NL2SbS2MO9droUu'
SecretKey = 'A3f04oHTO1NSGn20Xpqa2D8l8D2aqpXy'
# 初始化点播client
def initClient():
cred = credential.Credential(SecretId, SecretKey)
httpProfile = HttpProfile()
httpProfile.endpoint = "vod.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = vod_client.VodClient(cred, "", clientProfile)
return client
def doResponse(res):
# 处理返回结果
# 转变为常用返回Response
if hasattr(res, 'Error'):
return Response(res._serialize(allow_none=True), status=HTTP_400_BAD_REQUEST)
return Response(res._serialize(allow_none=True))
def getAllClass(params={}):
# 获取所有分类
try:
client = initClient()
req = models.DescribeAllClassRequest()
req.from_json_string(json.dumps(params))
resp = client.DescribeAllClass(req)
return doResponse(resp)
except TencentCloudSDKException as err:
print(err)
def searchMedia(params={}):
try:
client = initClient()
req = models.SearchMediaRequest()
req.from_json_string(json.dumps(params))
resp = client.SearchMedia(req)
return doResponse(resp)
except TencentCloudSDKException as err:
print(err)
def getSignature(procedure=None):
"""
获取上传签名
可指定
"""
TimeStamp = int(time.time())
ExpireTime = TimeStamp + 86400 * 365 * 10
Random = random.randint(0, 999999)
Original = "secretId=" + SecretId + "&currentTimeStamp=" + str(TimeStamp) + "&expireTime=" + str(ExpireTime) + "&random=" + str(Random)
if procedure:
Original = Original + "&procedure="+procedure
Hmac = hmac.new(bytes(SecretKey, 'utf-8'), bytes(Original, 'utf-8'), hashlib.sha1)
Sha1 = Hmac.digest()
Signature = bytes(Sha1) + bytes(Original, 'utf-8')
Signature2 = base64.b64encode(Signature)
return str(Signature2, 'UTF-8')