You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
7.8 KiB
220 lines
7.8 KiB
from rest_framework.generics import ListAPIView, RetrieveAPIView
|
|
from django.db.models import Count, Q, F
|
|
from drf_yasg.utils import swagger_auto_schema
|
|
from drf_yasg import openapi
|
|
from rest_framework.exceptions import NotFound
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.filters import SearchFilter
|
|
|
|
|
|
from apps.course.serializers import (
|
|
CourseListSerializer, CourseCategorySerializer, CourseDetailSerializer,
|
|
AttachmentSerializer, GlossarySerializer, MyCourseListSerializer
|
|
)
|
|
from apps.course.models import Course, CourseCategory, Attachment, Glossary, Participant
|
|
from apps.course.doc import *
|
|
|
|
|
|
class CourseCategoryAPIView(ListAPIView):
|
|
queryset = CourseCategory.objects.all()
|
|
serializer_class = CourseCategorySerializer
|
|
|
|
@swagger_auto_schema(
|
|
operation_description=doc_course_category(),
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
class CourseListAPIView(ListAPIView):
|
|
queryset = Course.objects.all().exclude(status=Course.StatusChoices.INACTIVE)
|
|
serializer_class = CourseListSerializer
|
|
filter_backends = [SearchFilter]
|
|
search_fields = ['title']
|
|
|
|
@swagger_auto_schema(
|
|
operation_description=doc_course_list(),
|
|
manual_parameters=[
|
|
openapi.Parameter(
|
|
'category_slug', openapi.IN_QUERY,
|
|
description="Category of the Course",
|
|
type=openapi.TYPE_STRING,
|
|
# enum=[category.slug for category in CourseCategory.objects.all()]
|
|
),
|
|
openapi.Parameter(
|
|
'status', openapi.IN_QUERY,
|
|
type=openapi.TYPE_STRING,
|
|
description="""Status =>
|
|
Upcoming (visible but registration not allowed)---Предстоящие
|
|
Registering (registration is open)---регистрация
|
|
Ongoing (course has started, registration closed)---Впроцессе
|
|
Finished (course has ended)---закончился
|
|
""",
|
|
enum=[status for status in ['upcoming', 'registering', 'ongoing', 'finished']]
|
|
),
|
|
openapi.Parameter(
|
|
'is_free', openapi.IN_QUERY,
|
|
description="Ценообразование is_free <bool>",
|
|
type=openapi.TYPE_BOOLEAN,
|
|
),
|
|
openapi.Parameter(
|
|
'is_online', openapi.IN_QUERY,
|
|
description="Статус участия is_online <bool>",
|
|
type=openapi.TYPE_BOOLEAN,
|
|
),
|
|
])
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset()
|
|
request = self.request
|
|
filters = request.query_params
|
|
|
|
# Handle category_slug with multiple values separated by commas
|
|
if category_slugs := filters.get('category_slug'):
|
|
category_slugs_list = category_slugs.split(',')
|
|
queryset = queryset.filter(category__slug__in=category_slugs_list)
|
|
|
|
# Handle status with multiple values separated by commas
|
|
if statuses := filters.get('status'):
|
|
statuses_list = statuses.split(',')
|
|
queryset = queryset.filter(status__in=statuses_list)
|
|
|
|
if is_free := filters.get('is_free'):
|
|
is_free = is_free.lower() == 'true'
|
|
queryset = queryset.filter(
|
|
Q(is_free=is_free) | Q(price=0) if is_free else Q(is_free=False, price__gt=0)
|
|
)
|
|
if is_online := filters.get('is_online'):
|
|
is_online = is_online.lower() == 'true'
|
|
queryset = queryset.filter(is_online=is_online)
|
|
|
|
return queryset
|
|
|
|
|
|
|
|
|
|
|
|
class CourseDetailAPIView(RetrieveAPIView):
|
|
queryset = Course.objects.all()
|
|
serializer_class = CourseDetailSerializer
|
|
lookup_field = "slug"
|
|
|
|
@swagger_auto_schema(
|
|
operation_description=doc_course_detail(),
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
|
|
class MyCourseListAPIView(ListAPIView):
|
|
serializer_class = MyCourseListSerializer
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
@swagger_auto_schema(manual_parameters=[
|
|
openapi.Parameter(
|
|
'completed', openapi.IN_QUERY,
|
|
description="мои курсы completed <bool> true",
|
|
type=openapi.TYPE_BOOLEAN,
|
|
),
|
|
openapi.Parameter(
|
|
'certificate', openapi.IN_QUERY,
|
|
type=openapi.TYPE_BOOLEAN,
|
|
),
|
|
],
|
|
operation_description=doc_courses_my_courses(),
|
|
operation_summary="Home",
|
|
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
print(f'--> my-course-> {request}/ {kwargs}')
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
queryset = Course.objects.exclude(status=Course.StatusChoices.INACTIVE)
|
|
request = self.request
|
|
filters = request.query_params
|
|
student = self.request.user
|
|
qs = queryset.filter(participants__student=student)
|
|
completed_only = filters.get('completed', '').lower() == 'true'
|
|
if completed_only == True:
|
|
# نمایش دورههایی که همه درسهایشان توسط کاربر تکمیل شدهاند
|
|
qs = qs.annotate(
|
|
total_lessons=Count('lessons', distinct=True),
|
|
completed_lessons=Count(
|
|
'lessons__completions',
|
|
filter=Q(lessons__completions__student=student),
|
|
distinct=True
|
|
)
|
|
).filter(total_lessons=F('completed_lessons'))
|
|
elif completed_only == False:
|
|
# نمایش دورههایی که همه درسهایشان تکمیل نشدهاند
|
|
qs = qs.annotate(
|
|
total_lessons=Count('lessons', distinct=True),
|
|
completed_lessons=Count(
|
|
'lessons__completions',
|
|
filter=Q(lessons__completions__student=student),
|
|
distinct=True
|
|
)
|
|
).filter(total_lessons__gt=F('completed_lessons'))
|
|
|
|
if 'completed' not in filters:
|
|
certificate = filters.get('certificate', '').lower() == 'true'
|
|
if certificate:
|
|
qs = qs.exclude(
|
|
course_certificates__student=student,
|
|
course_certificates__status__in=['pending', 'approved']
|
|
)
|
|
|
|
return qs
|
|
|
|
|
|
|
|
|
|
class AttachmentListAPIView(ListAPIView):
|
|
serializer_class = AttachmentSerializer
|
|
|
|
@swagger_auto_schema(
|
|
manual_parameters=[
|
|
openapi.Parameter(
|
|
'slug', openapi.IN_PATH,
|
|
description="Slug of the Course",
|
|
type=openapi.TYPE_STRING,
|
|
required=True
|
|
)
|
|
],
|
|
operation_description="Retrieve a list of attachments for a given course by its slug."
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
course_slug = self.kwargs.get('slug')
|
|
try:
|
|
course = Course.objects.get(slug=course_slug)
|
|
except Course.DoesNotExist:
|
|
raise NotFound("Course not found")
|
|
return Attachment.objects.filter(course=course)
|
|
|
|
|
|
|
|
|
|
class GlossaryListAPIView(ListAPIView):
|
|
serializer_class = GlossarySerializer
|
|
filter_backends = [SearchFilter]
|
|
search_fields = ['title', 'description']
|
|
|
|
def get_queryset(self):
|
|
course_slug = self.kwargs.get('slug')
|
|
try:
|
|
course = Course.objects.get(slug=course_slug)
|
|
except Course.DoesNotExist:
|
|
raise NotFound("Course not found")
|
|
|
|
return Glossary.objects.filter(course=course)
|
|
|
|
|
|
|