from paymentwall import Pingback from django.contrib.auth import get_user_model from django.contrib.auth.decorators import login_required from django.db.models import Q from django.http import JsonResponse, Http404 from django.shortcuts import get_object_or_404 from django.template import loader, Context, Template from django.views.generic import View, CreateView, DetailView, ListView, TemplateView from django.utils.cache import add_never_cache_headers from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from apps.payment.models import AuthorBalance from .models import Course, Like, Lesson, CourseComment, LessonComment from .filters import CourseFilter User = get_user_model() @login_required @csrf_exempt @require_http_methods(['POST']) def likes(request, course_id): try: course = Course.objects.prefetch_related('likes').get(id=course_id) except Course.DoesNotExist: return JsonResponse({ 'success': False, 'errors': ['Course with id f{cource_id} not found'] }, status=400) else: course_user_likes = course.likes.filter(user=request.user) if course_user_likes.exists(): is_liked = False for _course in course_user_likes.all(): course.likes.remove(_course) course_user_likes.delete() else: is_liked = True course.likes.add(Like.objects.create(user=request.user)) count = course.likes.count() return JsonResponse({ "success": True, "likes_count": count, "is_liked": is_liked, }) @login_required @csrf_exempt @require_http_methods(['POST']) def coursecomment(request, course_id): try: course = Course.objects.get(id=course_id) except Course.DoesNotExist: return JsonResponse({ 'success': False, 'errors': ['Course with id f{cource_id} not found'] }, status=400) else: reply_to = request.POST.get('reply_id', 0) comment = request.POST.get('comment', '') if not comment: return JsonResponse({ 'success': False, 'errors': ['Comment can not be empty'] }, status=400) if not int(reply_to): coursecomment = CourseComment.objects.create( author=request.user, content=comment, course=course, ) else: try: _coursecomment = CourseComment.objects.get(id=reply_to) except CourseComment.DoesNotExist: return JsonResponse({ 'success': False, 'errors': ['CourseComment with id f{reply_to} not found'] }, status=400) else: coursecomment = CourseComment.objects.create( author=request.user, content=comment, course=course, parent=_coursecomment, ) ctx = {'node': coursecomment, 'user': request.user} html = loader.render_to_string('templates/blocks/comment.html', ctx) return JsonResponse({ 'success': True, 'comment': html, }) @login_required @csrf_exempt @require_http_methods(['POST']) def lessoncomment(request, lesson_id): try: lesson = Lesson.objects.get(id=lesson_id) except Lesson.DoesNotExist: return JsonResponse({ 'success': False, 'errors': ['Lesson with id f{lesson_id} not found'] }, status=400) else: reply_to = request.POST.get('reply_id', 0) comment = request.POST.get('comment', '') if not comment: return JsonResponse({ 'success': False, 'errors': ['Comment can not be empty'] }, status=400) if not int(reply_to): lessoncomment = LessonComment.objects.create( author=request.user, content=comment, lesson=lesson, ) else: try: _lessoncomment = LessonComment.objects.get(id=reply_to) except LessonComment.DoesNotExist: return JsonResponse({ 'success': False, 'errors': ['LessonComment with id f{reply_to} not found'] }, status=400) else: lessoncomment = LessonComment.objects.create( author=request.user, content=comment, lesson=lesson, parent=_lessoncomment, ) ctx = {'node': lessoncomment, 'user': request.user} html = loader.render_to_string('templates/blocks/comment.html', ctx) return JsonResponse({ 'success': True, 'comment': html, }) @method_decorator(login_required, name='dispatch') class CourseOnModerationView(TemplateView): template_name = 'course/course_on_moderation.html' @method_decorator(login_required, name='dispatch') class CourseEditView(TemplateView): template_name = 'course/course_edit.html' def get(self, request, pk=None, lesson=None): drafts = Course.objects.filter( author=request.user, status=Course.DRAFT ) if pk: self.object = get_object_or_404(Course, pk=pk) elif drafts.exists(): self.object = drafts.last() else: self.object = Course.objects.create( author=request.user, ) if request.user != self.object.author and request.user.role not in [User.ADMIN_ROLE, User.AUTHOR_ROLE]: raise Http404 return super().get(request) def get_context_data(self): context = super().get_context_data() context['live'] = 'false' context['object'] = self.object return context @method_decorator(login_required, name='dispatch') class CourseLiveEditView(TemplateView): template_name = 'course/course_edit.html' def get(self, request, pk=None): drafts = Course.objects.filter( author=request.user, status=Course.DRAFT ) if pk: self.object = get_object_or_404(Course, pk=pk) elif drafts.exists(): self.object = drafts.last() else: self.object = Course.objects.create( author=request.user, ) if request.user != self.object.author and request.user.role not in [User.ADMIN_ROLE, User.AUTHOR_ROLE]: raise Http404 return super().get(request) def get_context_data(self): context = super().get_context_data() context['live'] = 'true' if self.object: context['object'] = self.object return context # @method_decorator(login_required, name='dispatch') class CourseView(DetailView): model = Course context_object_name = 'course' template_name = 'course/course.html' only_lessons = False def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) context = self.get_context_data() if (not request.user.is_authenticated and self.object.status != Course.PUBLISHED) or\ (request.user.is_authenticated and request.user.role not in [User.AUTHOR_ROLE, User.ADMIN_ROLE] and self.object.author != request.user and self.only_lessons and not context['paid']): raise Http404 return response # ((self.object.status != Course.PUBLISHED and request.user.role != User.ADMIN_ROLE) or # (self.object.status != Course.PUBLISHED and request.user.role != User.AUTHOR_ROLE and self.object.author != request.user)): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.request.user.is_authenticated: context['next'] = self.request.GET.get('next', None) context['paid'] = self.object.payments.filter( user=self.request.user, status__in=[ Pingback.PINGBACK_TYPE_REGULAR, Pingback.PINGBACK_TYPE_GOODWILL, Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, ], ).exists() context['pending'] = self.object.payments.filter( user=self.request.user, status=Pingback.PINGBACK_TYPE_RISK_UNDER_REVIEW, ).exists() context['only_lessons'] = self.only_lessons return context def get_queryset(self): queryset = super().get_queryset().select_related( 'author', 'category', ).prefetch_related( 'likes', 'materials', 'content', ) return queryset class CoursesView(ListView): model = Course context_object_name = 'course_items' paginate_by = 6 def get(self, request, *args, **kwargs): self.object_list = self.get_queryset() allow_empty = self.get_allow_empty() if request.is_ajax(): context = self.get_context_data() template_name = self.get_template_names() html = loader.render_to_string( template_name, context, request=request) is_paginated = context.get('is_paginated') if is_paginated: page_obj = context.get('page_obj') prev_url = request.path + '?page=' + \ str(page_obj.previous_page_number() ) if page_obj.has_previous() else None next_url = request.path + '?page=' + \ str(page_obj.next_page_number() ) if page_obj.has_next() else None else: prev_url = None next_url = None response = JsonResponse({ 'success': True, 'content': html, 'prev_url': prev_url, 'next_url': next_url, }) add_never_cache_headers(response) return response else: return super().get(request, args, kwargs) def get_queryset(self): queryset = super().get_queryset().select_related( 'author', 'category', 'cover', ).prefetch_related( 'likes', 'materials', 'content', ).filter(status=Course.PUBLISHED) filtered = CourseFilter(self.request.GET, queryset=queryset) return filtered.qs def get_context_data(self): context = super().get_context_data() filtered = CourseFilter(self.request.GET) context.update(filtered.data) return context def get_template_names(self): if self.request.is_ajax(): return 'course/course_items.html' return 'course/courses.html' @method_decorator(login_required, name='dispatch') class LessonView(DetailView): model = Lesson context_object_name = 'lesson' template_name = 'course/lesson.html' def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) if (self.object.course.status != Course.PUBLISHED and (request.user.role not in [User.AUTHOR_ROLE, User.ADMIN_ROLE] or self.object.course.author != request.user)): raise Http404 return response def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['next'] = self.request.GET.get('next', None) context['next_lesson'] = self.request.GET.get('next_lesson', None) return context class SearchView(CoursesView): template_name = 'course/result.html' def get_queryset(self): search_query = self.request.GET.get('q', None) queryset = super().get_queryset() if search_query: query = Q(title__icontains=search_query) | Q( short_description__icontains=search_query) queryset = queryset.filter(query) else: queryset = queryset.none() return queryset def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['q'] = self.request.GET.get('q', None) or '' return context if 'is_paginated' in context and context['is_paginated']: page_obj = context.get('page_obj') context['page'] = page_obj.number context['next_page'] = str( page_obj.next_page_number()) if page_obj.has_next() else None else: context['page'] = 1 context['next_page'] = None return context def get_template_names(self): if self.request.is_ajax(): return 'course/course_items.html' return 'course/result.html'