316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
from datetime import timedelta
 | 
						|
from time import timezone
 | 
						|
from apps.system.models import Dict
 | 
						|
from rest_framework.mixins import ListModelMixin, UpdateModelMixin
 | 
						|
from apps.vod.serializers import VRecordSerializer, VRecordUpdateSerializer, VideoListDetailSerializer, VideoSerializer, VideoUpdateSerializer, ViewItemSerializer, ViewItemUpdateSerializer, View2Serializer, DatetimeSerializer
 | 
						|
from apps.vod.models import Video, ViewRecord, ViewItem, View1, View2
 | 
						|
from django.shortcuts import render
 | 
						|
from .vodclient import getAllClass, getPlayCode, searchMedia, getSignature
 | 
						|
from rest_framework.views import APIView
 | 
						|
from rest_framework.response import Response
 | 
						|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
 | 
						|
from utils.pagination import PageOrNot
 | 
						|
from apps.system.mixins import CreateUpdateModelAMixin
 | 
						|
from rest_framework.decorators import action, permission_classes
 | 
						|
from rest_framework.permissions import IsAuthenticated
 | 
						|
from rest_framework.status import HTTP_400_BAD_REQUEST
 | 
						|
from django.utils import timezone
 | 
						|
from rest_framework.exceptions import ParseError
 | 
						|
from utils.queryset import get_child_queryset2
 | 
						|
from django.db.models import Sum
 | 
						|
from django.db import connection
 | 
						|
# Create your views here.
 | 
						|
 | 
						|
class ClassView(APIView):
 | 
						|
 | 
						|
    perms_map={'get':'*'}
 | 
						|
    def get(self, request, format=None):
 | 
						|
        """
 | 
						|
        查询分类
 | 
						|
        """
 | 
						|
        return getAllClass()
 | 
						|
 | 
						|
class VideoView(APIView):
 | 
						|
 | 
						|
    perms_map={'get':'video_view'}
 | 
						|
    def get(self, request, format=None):
 | 
						|
        """
 | 
						|
        查询视频
 | 
						|
        """
 | 
						|
        params={'Filters':['basicInfo', 'metaData']}
 | 
						|
        params['Offset'] = request.query_params.get('Offset', 0)
 | 
						|
        params['Limit'] = request.query_params.get('Limit', 20)
 | 
						|
        params['Names'] = request.query_params.getlist('name') if request.query_params.get('name') else []
 | 
						|
        params['ClassIds']= request.query_params.getlist('classid') if request.query_params.get('classid') else []
 | 
						|
        return searchMedia(params)
 | 
						|
 | 
						|
class VideoViewSet(PageOrNot, CreateUpdateModelAMixin, ModelViewSet):
 | 
						|
    perms_map={'get':'video_view', 'post':'video_create', 'put':'video_update', 'delete':'video_delete'}
 | 
						|
    queryset = Video.objects.all()
 | 
						|
    search_fields = ['name', 'category__name', 'description']
 | 
						|
    # filterset_fields = ['category']
 | 
						|
    serializer_class = VideoSerializer
 | 
						|
    ordering_fields = ['category__code', 'sort_str', 'views', 'viewsp']
 | 
						|
    ordering = ['category__code', 'sort_str']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action in ['list', 'retrieve']:
 | 
						|
            return VideoListDetailSerializer
 | 
						|
        elif self.action in ['update']:
 | 
						|
            return VideoUpdateSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
 | 
						|
    def get_queryset(self):
 | 
						|
        queryset = super().get_queryset()
 | 
						|
        category = self.request.query_params.get('category', None)
 | 
						|
        if category:
 | 
						|
            categorys = get_child_queryset2(Dict.objects.get(pk=category))
 | 
						|
            queryset = queryset.filter(category__in=categorys)
 | 
						|
        return queryset
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get':'video_view'})
 | 
						|
    def myview(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        废弃接口
 | 
						|
 | 
						|
        个人观看记录
 | 
						|
        """
 | 
						|
        queryset = ViewRecord.objects.filter(user=request.user).order_by('-id')
 | 
						|
        page = self.paginate_queryset(queryset)
 | 
						|
        if page is not None:
 | 
						|
            serializer = VRecordSerializer(page, many=True)
 | 
						|
            return self.get_paginated_response(serializer.data)
 | 
						|
        serializer = VRecordSerializer(queryset, many=True)
 | 
						|
        return Response(serializer.data)
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get':'*'})
 | 
						|
    def my(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        本视频的我的观看统计
 | 
						|
 | 
						|
        本视频的我的观看统计
 | 
						|
        """
 | 
						|
        video = self.get_object()
 | 
						|
        user = request.user
 | 
						|
        ins, _ = View2.objects.get_or_create(create_by=user, video=video, defaults={'video': video, 'create_by': user})
 | 
						|
        return Response(View2Serializer(instance=ins).data)
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get':'*'})
 | 
						|
    def start(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        开始播放
 | 
						|
 | 
						|
        本次播放开始返回记录ID,后续计时使用
 | 
						|
        """
 | 
						|
        video = self.get_object()
 | 
						|
        user = request.user
 | 
						|
        vi  = ViewItem.objects.create(create_by=user, video=video)
 | 
						|
        cal_view1(vi)
 | 
						|
        return Response({"vi": vi.id})
 | 
						|
 | 
						|
    # @action(methods=['get'], detail=False, perms_map={'get':'*'})
 | 
						|
    # def correct_cate(self, request, *args, **kwargs):
 | 
						|
    #     for video in Video.objects.get_queryset(all=True).all():
 | 
						|
    #         cate = video.category
 | 
						|
    #         video.category_big = cate
 | 
						|
    #         if cate.pid:
 | 
						|
    #             video.category_big = cate.pid
 | 
						|
    #         video.save()
 | 
						|
    #     return Response()
 | 
						|
 | 
						|
def cal_view1(vi: ViewItem):
 | 
						|
    """
 | 
						|
    统计视频播放数量
 | 
						|
 | 
						|
    统计视频播放数量
 | 
						|
    """
 | 
						|
    v1, _  = View1.objects.get_or_create(video=vi.video, defaults={"video": vi.video})
 | 
						|
    v2, _ =  View2.objects.get_or_create(video=vi.video, create_by=vi.create_by, defaults={"video": vi.video, "create_by": vi.create_by})
 | 
						|
    v1.views = ViewItem.objects.filter(video=vi.video).count()
 | 
						|
    v1.viewp = View2.objects.filter(video=vi.video).count()
 | 
						|
    v1.save()
 | 
						|
 | 
						|
def cal_view2(vi: ViewItem):
 | 
						|
    """
 | 
						|
    统计个人播放记录
 | 
						|
 | 
						|
    统计个人播放记录
 | 
						|
    """
 | 
						|
    v2, _ =  View2.objects.get_or_create(video=vi.video, create_by=vi.create_by, defaults={"video": vi.video, "create_by": vi.create_by})
 | 
						|
    v2.views = ViewItem.objects.filter(video=vi.video).count()
 | 
						|
    v2.total_seconds = ViewItem.objects.filter(video=vi.video).aggregate(total=Sum('total_seconds'))['total']
 | 
						|
    v2.save()
 | 
						|
 | 
						|
 | 
						|
class VRecordViewSet(ListModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    废弃接口
 | 
						|
 | 
						|
    废弃接口
 | 
						|
    """
 | 
						|
    perms_map = {'get':'viewrecord_view'}
 | 
						|
    queryset = ViewRecord.objects.all()
 | 
						|
    search_fields = ['user__name', 'video__name']
 | 
						|
    serializer_class = VRecordSerializer
 | 
						|
    ordering = ['-update_time']
 | 
						|
    
 | 
						|
 | 
						|
class ViewItemViewSet(ListModelMixin, UpdateModelMixin, GenericViewSet):
 | 
						|
    perms_map = {'get': 'viewitem_view', 'put': '*'}
 | 
						|
    queryset = ViewItem.objects.select_related('create_by', 'video').all()
 | 
						|
    search_fields = ['create_by__name', 'video__name']
 | 
						|
    serializer_class = ViewItemSerializer
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == "update":
 | 
						|
            return ViewItemUpdateSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get':'*'})
 | 
						|
    def my(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        我的观看记录
 | 
						|
 | 
						|
        我的观看记录
 | 
						|
        """
 | 
						|
        queryset = ViewItem.objects.filter(create_by=request.user).order_by('-id')
 | 
						|
        page = self.paginate_queryset(queryset)
 | 
						|
        if page is not None:
 | 
						|
            serializer = ViewItemSerializer(page, many=True)
 | 
						|
            return self.get_paginated_response(serializer.data)
 | 
						|
        serializer = ViewItemSerializer(queryset, many=True)
 | 
						|
        return Response(serializer.data)
 | 
						|
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        user = request.user
 | 
						|
        data = request.data
 | 
						|
        obj = self.get_object()
 | 
						|
        if obj.create_by != user:
 | 
						|
            raise ParseError('非创建人')
 | 
						|
        if ViewItem.objects.filter(video=obj.video, create_by=user).order_by('-id').first() != obj:
 | 
						|
            raise ParseError('存在新播放记录')
 | 
						|
        obj.current = data['current']
 | 
						|
        obj.total_seconds = obj.total_seconds + data['seconds']
 | 
						|
        obj.save()
 | 
						|
        cal_view2(obj)
 | 
						|
        return Response({'id': obj.id, 'current': obj.current, 'total_seconds': obj.total_seconds})
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get':'*'})
 | 
						|
    def complete(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        完成播放
 | 
						|
 | 
						|
        完成播放
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        obj.current = 0
 | 
						|
        v2 = View2.objects.get(video=obj.video, create_by=obj.create_by)
 | 
						|
        if v2.total_seconds >= obj.video.duration * 0.6:
 | 
						|
            v2.is_completed = True
 | 
						|
            v2.save()
 | 
						|
            return Response()
 | 
						|
        raise ParseError('观看时长不足')
 | 
						|
 | 
						|
class View2ViewSet(ListModelMixin, GenericViewSet):
 | 
						|
    perms_map = {'get': 'view2_view', 'put': '*'}
 | 
						|
    queryset = View2.objects.select_related('create_by', 'video').all()
 | 
						|
    search_fields = ['create_by__name', 'video__name']
 | 
						|
    serializer_class = View2Serializer
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get':'*'})
 | 
						|
    def my(self, request, *args, **kwargs):
 | 
						|
        """
 | 
						|
        我的观看统计
 | 
						|
 | 
						|
        我的观看统计
 | 
						|
        """
 | 
						|
        queryset = View2.objects.filter(create_by=request.user).order_by('-id')
 | 
						|
        page = self.paginate_queryset(queryset)
 | 
						|
        if page is not None:
 | 
						|
            serializer = View2Serializer(page, many=True)
 | 
						|
            return self.get_paginated_response(serializer.data)
 | 
						|
        serializer = View2Serializer(queryset, many=True)
 | 
						|
        return Response(serializer.data)
 | 
						|
 | 
						|
 | 
						|
class MyViewRecordAPIView(APIView):
 | 
						|
 | 
						|
    permission_classes = [IsAuthenticated]
 | 
						|
    def get(self, request, id , format=None):
 | 
						|
        """
 | 
						|
        废弃接口
 | 
						|
 | 
						|
        该视频的本人观看信息
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            video = Video.objects.get(pk=id)
 | 
						|
        except:
 | 
						|
            return Response('视频不存在', status=HTTP_400_BAD_REQUEST)
 | 
						|
        record = ViewRecord.objects.filter(video=video, user=request.user).first()
 | 
						|
        if record:
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            record = ViewRecord.objects.create(video=video, user=request.user)
 | 
						|
        serializer = VRecordSerializer(instance=record)
 | 
						|
        return Response(serializer.data)
 | 
						|
 | 
						|
    def put(self, request, id, format=None):
 | 
						|
        """
 | 
						|
        废弃接口
 | 
						|
 | 
						|
        更新该视频本人的观看信息
 | 
						|
        params: {current:int}
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            video = Video.objects.get(pk=id)
 | 
						|
        except:
 | 
						|
            return Response('视频不存在', status=HTTP_400_BAD_REQUEST)
 | 
						|
        
 | 
						|
        record = ViewRecord.objects.filter(video=video, user=request.user).first()
 | 
						|
        fcreated = True
 | 
						|
        if record:
 | 
						|
            fcreated = False
 | 
						|
        else:
 | 
						|
            record = ViewRecord.objects.create(video=video, user=request.user)
 | 
						|
 | 
						|
        if fcreated:
 | 
						|
            video.viewsp = video.viewsp + 1
 | 
						|
            video.views = video.views + 1
 | 
						|
            record.views = 1
 | 
						|
            video.save()
 | 
						|
        if request.data.get('current', None):
 | 
						|
            record.current = request.data.get('current')
 | 
						|
        if timezone.now() > record.update_time + timedelta(minutes=30):
 | 
						|
            record.views = record.views + 1
 | 
						|
            video.views = video.views + 1
 | 
						|
            video.save()
 | 
						|
        else:
 | 
						|
            record.total_seconds = record.total_seconds + 10
 | 
						|
            record.save()
 | 
						|
        record.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class SignatureAPIView(APIView):
 | 
						|
    perms_map={'get':'video_create'}
 | 
						|
    def get(self, request, format=None):
 | 
						|
        """
 | 
						|
        获取上传签名
 | 
						|
        """
 | 
						|
        return Response(getSignature(procedure=request.query_params.get('procedure', None)))
 | 
						|
 | 
						|
 | 
						|
class PlayCodeAPIView(APIView):
 | 
						|
    permission_classes = [IsAuthenticated]
 | 
						|
 | 
						|
    def get(self, request, fileId):
 | 
						|
        """获取播放签名
 | 
						|
        """
 | 
						|
        from .vodclient import appId
 | 
						|
        try:
 | 
						|
            playcode = getPlayCode(fileId)
 | 
						|
        except:
 | 
						|
            raise ParseError('获取签名失败')
 | 
						|
        return Response({'psign':playcode, 'appId': appId})
 |