123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- from django.db.models import Count
- from django.utils import timezone
- from drf_yasg import openapi
- from drf_yasg.utils import swagger_auto_schema
- from rest_framework import status
- from rest_framework.generics import GenericAPIView
- from rest_framework.mixins import UpdateModelMixin, CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, ListModelMixin
- from rest_framework.response import Response
- from rest_framework.views import APIView
- from .querysets import ALL_UBC_QUERYSET
- from .serializers import UsersBooksCollectionsSerializer, UsersBooksCollectionsPostSerializer
- from api.permissions import AllowAny, IsAuthenticated, IsAdmin
- from content.models import UsersBooksCollections, Collection, Book, Author, Genre
- from ..author.serializers import AuthorSerializer
- from ..genre.serializers import GenreSerializer
- from ..permissions import IsStaffOrAdmin
- # region base
- class UBCAPIView(GenericAPIView):
- queryset = ALL_UBC_QUERYSET
- serializer_class = UsersBooksCollectionsSerializer
- permission_classes = [AllowAny]
- ordering_fields = ["created_at"]
- ordering = ["-created_at"]
- class UBCMEAPIView(UBCAPIView):
- permission_classes = [IsAuthenticated,]
- def get_queryset(self):
- return ALL_UBC_QUERYSET.filter(user=self.request.user)
- class UBCMECOLLAPIView(UBCAPIView):
- permission_classes = [IsAuthenticated,]
- def get_queryset(self):
- collection_uuid = self.kwargs["collection_uuid"]
- return ALL_UBC_QUERYSET.filter(user=self.request.user, collection__uuid=collection_uuid)
- # endregion
- # region private
- class UBCListView(ListModelMixin, CreateModelMixin, UBCAPIView):
- permission_classes = [IsStaffOrAdmin]
- def get(self, request, *args, **kwargs):
- return self.list(request, *args, **kwargs)
- # endregion
- # region public
- class TopReadAPIView(APIView):
- permission_classes = [IsAuthenticated,]
- def get(self, request):
- collections = Collection.objects.filter(title__in=["Читаемое", "Прочитано"])
- books = Book.objects.filter(
- usersbookscollections__user=request.user,
- usersbookscollections__collection__in=collections
- ).prefetch_related('genres', 'authors')
- top_authors = (
- books.values('authors__id', 'authors__name')
- .annotate(read_count=Count('usersbookscollections'))
- .order_by('-read_count')[:3]
- )
- top_genres = (
- books.values('genres__id', 'genres__title')
- .annotate(read_count=Count('usersbookscollections'))
- .order_by('-read_count')[:3]
- )
- top_authors_data = [
- {'id': author['authors__id'], 'name': author['authors__name']}
- for author in top_authors
- ]
- top_genres_data = [
- {'id': genre['genres__id'], 'name': genre['genres__title']}
- for genre in top_genres
- ]
- return Response({
- 'top_authors': top_authors_data,
- 'top_genres': top_genres_data
- })
- class CheckBookInBookmarksView(APIView):
- permission_classes = [IsAuthenticated,]
- def get(self, request, book_uuid):
- user = request.user
- try:
- bookmark = UsersBooksCollections.objects.get(user=user, book__uuid=book_uuid, collection__title='Закладки')
- return Response({"exists": True}, status=status.HTTP_200_OK)
- except UsersBooksCollections.DoesNotExist:
- return Response({"exists": False}, status=status.HTTP_200_OK)
- class UBCMEListView(UBCMEAPIView, ListModelMixin):
- def get(self, request, *args, **kwargs):
- return self.list(request, *args, **kwargs)
- class UBCMECreateView(UBCMEAPIView, CreateModelMixin):
- serializer_class = UsersBooksCollectionsPostSerializer
- def post(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.data)
- serializer.is_valid(raise_exception=True)
- self.perform_create(serializer)
- return Response(serializer.data, status=status.HTTP_201_CREATED)
- def perform_create(self, serializer):
- serializer.save(user=self.request.user)
- class UBCMECOLLListView(ListModelMixin, UBCMECOLLAPIView):
- def get(self, request, *args, **kwargs):
- return self.list(request, *args, **kwargs)
- class UBCMERetrieveUpdateDestroyView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, UBCMEAPIView):
- def get(self, request, *args, **kwargs):
- return self.retrieve(request, *args, **kwargs)
- def put(self, request, *args, **kwargs):
- return self.update(request, *args, **kwargs)
- def patch(self, request, *args, **kwargs):
- return self.partial_update(request, *args, **kwargs)
- def delete(self, request, *args, **kwargs):
- return self.destroy(request, *args, **kwargs)
- def perform_destroy(self, instance):
- instance.delete()
- class CountReadBooksView(APIView):
- permission_classes = [IsAuthenticated,]
- @swagger_auto_schema(
- manual_parameters=[
- openapi.Parameter(
- 'start_date',
- openapi.IN_QUERY,
- description="Начальная дата в формате ISO 8601 (2023-12-31T23:59:59)",
- type=openapi.TYPE_STRING,
- format=openapi.FORMAT_DATETIME,
- required=True
- ),
- openapi.Parameter(
- 'end_date',
- openapi.IN_QUERY,
- description="Конечная дата в формате ISO 8601 (2023-12-31T23:59:59)",
- type=openapi.TYPE_STRING,
- format=openapi.FORMAT_DATETIME,
- required=True
- ),
- ], )
- def get(self, request):
- user = request.user
- start_date = request.query_params.get('start_date')
- end_date = request.query_params.get('end_date')
- if not start_date or not end_date:
- return Response({"error": "Диапазон дат не предоставлен"}, status=status.HTTP_400_BAD_REQUEST)
- try:
- start_date = timezone.datetime.fromisoformat(start_date)
- end_date = timezone.datetime.fromisoformat(end_date)
- except ValueError:
- return Response({"error": "Некорректный формат переданных дат"}, status=status.HTTP_400_BAD_REQUEST)
- count = UsersBooksCollections.objects.filter(
- user=user,
- collection__title='Прочитано',
- created_at__range=(start_date, end_date)
- ).count()
- return Response({"count": count}, status=status.HTTP_200_OK)
- # endregion
|