4 changed files with 249 additions and 3 deletions
-
8apps/library/serializers.py
-
152apps/library/serializers_admin.py
-
12apps/library/urls.py
-
80apps/library/views_admin.py
@ -0,0 +1,152 @@ |
|||||
|
from rest_framework import serializers |
||||
|
|
||||
|
from .models import Book, BookCollection, Category |
||||
|
|
||||
|
|
||||
|
class AbsoluteImageField(serializers.ImageField): |
||||
|
def to_representation(self, value): |
||||
|
if not value: |
||||
|
return None |
||||
|
request = self.context.get("request") |
||||
|
url = value.url if hasattr(value, "url") else str(value) |
||||
|
if request: |
||||
|
return request.build_absolute_uri(url) |
||||
|
return url |
||||
|
|
||||
|
|
||||
|
class AbsoluteFileField(serializers.FileField): |
||||
|
def to_representation(self, value): |
||||
|
if not value: |
||||
|
return None |
||||
|
request = self.context.get("request") |
||||
|
url = value.url if hasattr(value, "url") else str(value) |
||||
|
if request: |
||||
|
return request.build_absolute_uri(url) |
||||
|
return url |
||||
|
|
||||
|
|
||||
|
class AdminLibraryCategorySerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = Category |
||||
|
fields = ["id", "title", "slug", "status", "created_at", "updated_at"] |
||||
|
|
||||
|
|
||||
|
class AdminLibraryCollectionSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = BookCollection |
||||
|
fields = ["id", "title", "slug", "summary", "display_position", "status", "order", "pin_top"] |
||||
|
|
||||
|
|
||||
|
class AdminBookListSerializer(serializers.ModelSerializer): |
||||
|
thumbnail = AbsoluteImageField(required=False, allow_null=True) |
||||
|
book_file = AbsoluteFileField(required=False, allow_null=True) |
||||
|
categories_detail = AdminLibraryCategorySerializer(source="categories", many=True, read_only=True) |
||||
|
|
||||
|
class Meta: |
||||
|
model = Book |
||||
|
fields = [ |
||||
|
"id", |
||||
|
"title", |
||||
|
"slug", |
||||
|
"slogan", |
||||
|
"thumbnail", |
||||
|
"author", |
||||
|
"publisher", |
||||
|
"file_type", |
||||
|
"status", |
||||
|
"pin", |
||||
|
"view_count", |
||||
|
"download_count", |
||||
|
"created_at", |
||||
|
"updated_at", |
||||
|
"categories_detail", |
||||
|
"book_file", |
||||
|
] |
||||
|
read_only_fields = ["id", "view_count", "download_count", "created_at", "updated_at"] |
||||
|
|
||||
|
from dj_language.models import Language |
||||
|
class AdminBookDetailSerializer(serializers.ModelSerializer): |
||||
|
thumbnail = AbsoluteImageField(required=False, allow_null=True) |
||||
|
book_file = AbsoluteFileField(required=False, allow_null=True) |
||||
|
categories = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True, required=False) |
||||
|
collections = serializers.PrimaryKeyRelatedField(queryset=BookCollection.objects.all(), many=True, required=False) |
||||
|
categories_detail = AdminLibraryCategorySerializer(source="categories", many=True, read_only=True) |
||||
|
collections_detail = AdminLibraryCollectionSerializer(source="collections", many=True, read_only=True) |
||||
|
remove_thumbnail = serializers.BooleanField(write_only=True, required=False, default=False) |
||||
|
remove_book_file = serializers.BooleanField(write_only=True, required=False, default=False) |
||||
|
language = serializers.SlugRelatedField( |
||||
|
slug_field='code', |
||||
|
queryset=Language.objects.all(), |
||||
|
allow_null=True, |
||||
|
required=False |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
model = Book |
||||
|
fields = [ |
||||
|
"id", |
||||
|
"title", |
||||
|
"slug", |
||||
|
"slogan", |
||||
|
"summary_title", |
||||
|
"summary", |
||||
|
"description", |
||||
|
"thumbnail", |
||||
|
"publisher", |
||||
|
"year_of_publication", |
||||
|
"author", |
||||
|
"isbn", |
||||
|
"numnber_of_volume", |
||||
|
"language", |
||||
|
"main_themes", |
||||
|
"notable_works", |
||||
|
"pages_count", |
||||
|
"status", |
||||
|
"pin", |
||||
|
"view_count", |
||||
|
"download_count", |
||||
|
"file_type", |
||||
|
"book_file", |
||||
|
"created_at", |
||||
|
"updated_at", |
||||
|
"categories", |
||||
|
"collections", |
||||
|
"categories_detail", |
||||
|
"collections_detail", |
||||
|
"remove_thumbnail", |
||||
|
"remove_book_file", |
||||
|
] |
||||
|
read_only_fields = ["id", "view_count", "download_count", "created_at", "updated_at"] |
||||
|
|
||||
|
def create(self, validated_data): |
||||
|
validated_data.pop("remove_thumbnail", False) |
||||
|
validated_data.pop("remove_book_file", False) |
||||
|
categories = validated_data.pop("categories", []) |
||||
|
collections = validated_data.pop("collections", []) |
||||
|
book = super().create(validated_data) |
||||
|
if categories: |
||||
|
book.categories.set(categories) |
||||
|
if collections: |
||||
|
book.collections.set(collections) |
||||
|
return book |
||||
|
|
||||
|
def update(self, instance, validated_data): |
||||
|
remove_thumbnail = validated_data.pop("remove_thumbnail", False) |
||||
|
remove_book_file = validated_data.pop("remove_book_file", False) |
||||
|
categories = validated_data.pop("categories", None) |
||||
|
collections = validated_data.pop("collections", None) |
||||
|
|
||||
|
if remove_thumbnail and instance.thumbnail: |
||||
|
instance.thumbnail.delete(save=False) |
||||
|
instance.thumbnail = None |
||||
|
|
||||
|
if remove_book_file and instance.book_file: |
||||
|
instance.book_file.delete(save=False) |
||||
|
instance.book_file = None |
||||
|
|
||||
|
book = super().update(instance, validated_data) |
||||
|
if categories is not None: |
||||
|
book.categories.set(categories) |
||||
|
if collections is not None: |
||||
|
book.collections.set(collections) |
||||
|
return book |
||||
@ -0,0 +1,80 @@ |
|||||
|
from django.db.models import Q |
||||
|
from rest_framework.authentication import TokenAuthentication |
||||
|
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser |
||||
|
from rest_framework.permissions import IsAuthenticated |
||||
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet |
||||
|
|
||||
|
from apps.account.permissions import IsSuperAdmin |
||||
|
from utils.pagination import StandardResultsSetPagination |
||||
|
|
||||
|
from .models import Book, BookCollection, Category |
||||
|
from .serializers_admin import ( |
||||
|
AdminBookDetailSerializer, |
||||
|
AdminBookListSerializer, |
||||
|
AdminLibraryCategorySerializer, |
||||
|
AdminLibraryCollectionSerializer, |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AdminLibraryCategoryViewSet(ReadOnlyModelViewSet): |
||||
|
serializer_class = AdminLibraryCategorySerializer |
||||
|
permission_classes = [IsAuthenticated, IsSuperAdmin] |
||||
|
authentication_classes = [TokenAuthentication] |
||||
|
pagination_class = None |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return Category.objects.all().order_by("title") |
||||
|
|
||||
|
|
||||
|
class AdminLibraryCollectionViewSet(ReadOnlyModelViewSet): |
||||
|
serializer_class = AdminLibraryCollectionSerializer |
||||
|
permission_classes = [IsAuthenticated, IsSuperAdmin] |
||||
|
authentication_classes = [TokenAuthentication] |
||||
|
pagination_class = None |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return BookCollection.objects.all().order_by("display_position", "order", "title") |
||||
|
|
||||
|
|
||||
|
class AdminBookViewSet(ModelViewSet): |
||||
|
permission_classes = [IsAuthenticated, IsSuperAdmin] |
||||
|
authentication_classes = [TokenAuthentication] |
||||
|
pagination_class = StandardResultsSetPagination |
||||
|
parser_classes = (MultiPartParser, FormParser, JSONParser) |
||||
|
|
||||
|
def get_serializer_class(self): |
||||
|
if self.action == "list": |
||||
|
return AdminBookListSerializer |
||||
|
return AdminBookDetailSerializer |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
queryset = Book.objects.all().prefetch_related("categories", "collections") |
||||
|
|
||||
|
search_query = self.request.query_params.get("search") |
||||
|
if search_query: |
||||
|
queryset = queryset.filter( |
||||
|
Q(title__icontains=search_query) |
||||
|
| Q(slug__icontains=search_query) |
||||
|
| Q(author__icontains=search_query) |
||||
|
| Q(publisher__icontains=search_query) |
||||
|
| Q(isbn__icontains=search_query) |
||||
|
| Q(summary__icontains=search_query) |
||||
|
) |
||||
|
|
||||
|
status_filter = self.request.query_params.get("status") |
||||
|
if status_filter in {"true", "false"}: |
||||
|
queryset = queryset.filter(status=status_filter == "true") |
||||
|
|
||||
|
file_type = self.request.query_params.get("file_type") |
||||
|
if file_type and file_type != "all": |
||||
|
queryset = queryset.filter(file_type=file_type) |
||||
|
|
||||
|
category_id = self.request.query_params.get("category") |
||||
|
if category_id and category_id != "all": |
||||
|
queryset = queryset.filter(categories__id=category_id) |
||||
|
|
||||
|
collection_id = self.request.query_params.get("collection") |
||||
|
if collection_id and collection_id != "all": |
||||
|
queryset = queryset.filter(collections__id=collection_id) |
||||
|
|
||||
|
return queryset.distinct().order_by("-created_at") |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue