from django.contrib.auth import get_user_model from rest_framework import status, views, viewsets, generics from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response from . import ExtendedModelViewSet from .serializers.config import ConfigSerializer from .serializers.course import ( CategorySerializer, LikeSerializer, CourseSerializer, CourseCreateSerializer, CourseBulkChangeCategorySerializer, CommentSerializer, MaterialSerializer, MaterialCreateSerializer, LessonSerializer, LessonCreateSerializer, ) from .serializers.content import ( BanerSerializer, ImageSerializer, ImageCreateSerializer, TextSerializer, TextCreateSerializer, ImageTextSerializer, ImageTextCreateSerializer, VideoSerializer, VideoCreateSerializer, GallerySerializer, GalleryImageSerializer, GalleryImageCreateSerializer, ImageObjectSerializer, ) from .serializers.school import ( SchoolScheduleSerializer, LiveLessonCreateSerializer, LiveLessonSerializer, ) from .serializers.payment import ( AuthorBalanceSerializer, AuthorBalanceCreateSerializer, PaymentSerializer, CoursePaymentSerializer, SchoolPaymentSerializer, ) from .serializers.user import ( AuthorRequestSerializer, UserSerializer, UserPhotoSerializer, ) from .permissions import ( IsAdmin, IsAdminOrIsSelf, IsAuthorOrAdmin, IsAuthorObjectOrAdmin, IsTeacherOrAdmin, ) from apps.course.models import ( Category, Course, Comment, CourseComment, LessonComment, Material, Lesson, Like, ) from apps.config.models import Config from apps.content.models import ( Baner, Image, Text, ImageText, Video, Gallery, GalleryImage, ImageObject, ) from apps.payment.models import ( AuthorBalance, Payment, CoursePayment, SchoolPayment, ) from apps.school.models import SchoolSchedule, LiveLesson from apps.user.models import AuthorRequest User = get_user_model() class AuthorBalanceViewSet(ExtendedModelViewSet): queryset = AuthorBalance.objects.filter( author__role__in=[User.AUTHOR_ROLE, User.ADMIN_ROLE], ) serializer_class = AuthorBalanceCreateSerializer serializer_class_map = { 'list': AuthorBalanceSerializer, } permission_classes = (IsAdmin,) filter_fields = ('author', 'status', 'type') search_fields = ( 'author__email', 'author__first_name', 'author__last_name', ) class BanerViewSet(ExtendedModelViewSet): queryset = Baner.objects.all() serializer_class = BanerSerializer permission_classes = (IsAdmin,) filter_fields = ('use',) ordering_fields = ('created_at', 'update_at',) search_fields = ('text',) def perform_create(self, serializer): files = dict() for k, v in self.request.FILES.items(): if v: files[k] = v serializer.save(**files) def perform_update(self, serializer): files = dict() for k, v in self.request.FILES.items(): if v: files[k] = v serializer.save(**files) class ImageObjectViewSet(ExtendedModelViewSet): queryset = ImageObject.objects.all() serializer_class = ImageObjectSerializer # permission_classes = (IsAuthorOrAdmin,) class MaterialViewSet(ExtendedModelViewSet): queryset = Material.objects.all() serializer_class = MaterialCreateSerializer serializer_class_map = { 'list': MaterialSerializer, 'retrieve': MaterialSerializer, } search_fields = ('title', 'short_description',) ordering_fields = ('title', 'created_at', 'update_at',) # permission_classes = (IsAdmin,) class LikeViewSet(ExtendedModelViewSet): queryset = Like.objects.select_related('user').all() serializer_class = LikeSerializer search_fields = ('user__email', 'user__firstname', 'user__lastname',) ordering_fields = ('created_at', 'update_at',) # permission_classes = (IsAdmin,) class CategoryViewSet(ExtendedModelViewSet): queryset = Category.objects.order_by('-id') serializer_class = CategorySerializer search_fields = ('title',) ordering_fields = ('title',) # permission_classes = (IsAdmin,) class CourseViewSet(ExtendedModelViewSet): queryset = Course.objects.select_related( 'author', 'category', 'cover', 'gallery', ).prefetch_related( 'likes', 'materials', 'content', ).all() serializer_class = CourseCreateSerializer serializer_class_map = { 'list': CourseSerializer, 'retrieve': CourseSerializer, 'draft': CourseSerializer, 'change_category_bulk': CourseBulkChangeCategorySerializer, } filter_fields = ('category', 'status', 'is_infinite', 'is_featured',) search_fields = ('author__email', 'title', 'category__title',) ordering_fields = ('id', 'title', 'created_at', 'update_at',) # permission_classes = (IsAuthorObjectOrAdmin,) # permission_map = { # 'create': IsAuthorOrAdmin, # 'delete': IsAdmin, # } @list_route(methods=['get']) def draft(self, request): drafts = Course.objects.filter(author=request.user, status=Course.DRAFT) serializer = self.get_serializer_class() serialized_data = serializer(instance=drafts.last()) return Response(serialized_data.data) @list_route(methods=['patch'], url_path='change-category-bulk') def change_category_bulk(self, request): serializer_class = self.get_serializer_class() serializer = serializer_class(data=request.data) if serializer.is_valid(): old_category_id = serializer.validated_data['old_category'] new_category_id = serializer.validated_data['new_category'] try: old_category = Category.objects.get(id=old_category_id) except Category.DoesNotExist: return Response( {'success': False, 'detail': f'Category with id {old_category_id} not found'}, status=status.HTTP_400_BAD_REQUEST, ) try: new_category = Category.objects.get(id=new_category_id) except Category.DoesNotExist: return Response( {'success': False, 'detail': f'Category with id {new_category_id} not found'}, status=status.HTTP_400_BAD_REQUEST, ) c = Course.objects.filter( category=old_category, ).update( category=new_category ) return Response({'success': True}) else: return Response( {'success': False}, status=status.HTTP_400_BAD_REQUEST, ) class LessonViewSet(ExtendedModelViewSet): queryset = Lesson.objects.select_related( 'course', 'cover' ).prefetch_related('content').all() serializer_class = LessonCreateSerializer serializer_class_map = { 'list': LessonSerializer, 'retrieve': LessonSerializer, } filter_fields = ('course',) search_fields = ('title', 'short_description',) ordering_fields = ('title', 'created_at', 'update_at',) permission_classes = (IsAuthorObjectOrAdmin,) permission_map = { 'create': IsAuthorOrAdmin, 'delete': IsAdmin, } class LiveLessonViewSet(ExtendedModelViewSet): queryset = LiveLesson.objects.prefetch_related('content').all() serializer_class = LiveLessonCreateSerializer serializer_class_map = { 'list': LiveLessonSerializer, 'retrieve': LiveLessonSerializer, } search_fields = ('title', 'short_description',) ordering_fields = ('title', 'created_at', 'update_at',) permission_classes = (IsTeacherOrAdmin,) permission_map = { 'delete': IsAdmin, } class ImageViewSet(ExtendedModelViewSet): queryset = Image.objects.select_related( 'course', 'lesson', 'img', ).all() serializer_class = ImageCreateSerializer serializer_class_map = { 'list': ImageSerializer, 'retrieve': ImageSerializer, } search_fields = ('title',) ordering_fields = ('title', 'created_at', 'update_at', 'position',) # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class TextViewSet(ExtendedModelViewSet): queryset = Text.objects.select_related( 'course', 'lesson' ).all() serializer_class = TextCreateSerializer serializer_class_map = { 'list': TextSerializer, 'retrieve': TextSerializer, } search_fields = ('title',) ordering_fields = ('title', 'created_at', 'update_at', 'position',) # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class ImageTextViewSet(ExtendedModelViewSet): queryset = ImageText.objects.select_related( 'course', 'lesson', 'img' ).all() serializer_class = ImageTextCreateSerializer serializer_class_map = { 'list': ImageTextSerializer, 'retrieve': ImageTextSerializer, } search_fields = ('title',) ordering_fields = ('title', 'created_at', 'update_at', 'position',) # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class VideoViewSet(ExtendedModelViewSet): queryset = Video.objects.select_related( 'course', 'lesson' ).all() serializer_class = VideoCreateSerializer serializer_class_map = { 'list': VideoSerializer, 'retrieve': VideoSerializer, } search_fields = ('title',) ordering_fields = ('title', 'created_at', 'update_at', 'position',) # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class GalleryViewSet(ExtendedModelViewSet): queryset = Gallery.objects.all() serializer_class = GallerySerializer search_fields = ('title',) ordering_fields = ('title', 'created_at', 'update_at',) # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class GalleryImageViewSet(ExtendedModelViewSet): queryset = GalleryImage.objects.select_related( 'gallery', 'img', ).all() serializer_class = GalleryImageCreateSerializer search_fields = ('gallery__title',) serializer_class_map = { 'list': GalleryImageSerializer, 'retrieve': GalleryImageSerializer, } # permission_classes = (IsAuthorOrAdmin,) # permission_map = { # 'delete': IsAdmin, # } class UserViewSet(ExtendedModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer serializer_class_map = { 'upload_photo': UserPhotoSerializer, } filter_fields = ('is_staff', 'is_active', 'role', 'gender', 'is_email_proved', 'fb_id',) search_fields = ('email', 'first_name', 'last_name', 'country', 'city', 'fb_id',) ordering_fields = ('email', 'first_name', 'last_name', 'country', 'city', 'date_joined',) # permission_classes = (IsAdminOrIsSelf,) # permission_map = { # 'delete': IsAdmin, # } @list_route(methods=['get']) def me(self, request): serializer = self.get_serializer_class() serialized_data = serializer(instance=request.user) return Response(serialized_data.data) @detail_route(methods=['post'], url_path='upload-photo') def upload_photo(self, request, pk=None): user = self.get_object() serializer = self.get_serializer() serialized_data = serializer(data=request.data) if serialized_data.is_valid(): user.photo = serialized_data['photo'] user.save() return Response({'success': True}) else: return Response({'success': False}, status=status.HTTP_400_BAD_REQUEST) class SchoolScheduleViewSet(ExtendedModelViewSet): queryset = SchoolSchedule.objects.all() serializer_class = SchoolScheduleSerializer permission_classes = (IsTeacherOrAdmin,) class ConfigViewSet(generics.RetrieveUpdateAPIView): queryset = Config.objects.all() serializer_class = ConfigSerializer permission_classes = (IsAdmin,) def perform_update(self, serializer): files = dict() for k, v in self.request.FILES.items(): if v: files[k] = v serializer.save(**files) def get_object(self): return Config.load() class CommentViewSet(ExtendedModelViewSet): queryset = Comment.objects.filter(level=0) serializer_class = CommentSerializer permission_classes = (IsAdmin,) def get_queryset(self): queryset = self.queryset is_deactivated = self.request.query_params.get('is_deactivated', '0') if is_deactivated == '0': queryset = queryset elif is_deactivated == '1': queryset = queryset.filter(deactivated_at__isnull=True) elif is_deactivated == '2': queryset = queryset.filter(deactivated_at__isnull=False) return queryset class AuthorRequestViewSet(ExtendedModelViewSet): queryset = AuthorRequest.objects.all() serializer_class = AuthorRequestSerializer permission_classes = (IsAdmin,) filter_fields = ('status',) class PaymentViewSet(ExtendedModelViewSet): queryset = Payment.objects.all() serializer_class = PaymentSerializer permission_classes = (IsAdmin,) filter_fields = ('status', 'user',) ordering_fields = ( 'id', 'user__email', 'user__first_name', 'user__last_name', 'amount', 'created_at', ) search_fields = ('user__email', 'user__first_name', 'user__last_name',) def get_queryset(self): queryset = self.queryset course = self.request.query_params.get('course') weekdays = self.request.query_params.getlist('weekdays[]') if course: queryset = CoursePayment.objects.filter(course=course) if weekdays: queryset = SchoolPayment.objects.filter(weekdays__overlap=weekdays) return queryset.filter(status__isnull=False).order_by('-created_at')