책 리뷰 사이트 02

·2023년 10월 10일
0

웹 프로젝트

목록 보기
6/18

이전에 짜뒀던 API 를 구체적으로 다듬은 다음 모델과 serializer 에서 키에러가 나길래 이것도 조금 수정했다.
특히 views.py 에서 쿼리셋을 .value() 로 받아 serializer 처리를 하는 중 키에러가 나서 serializers.SerializerMethodField() 으로 시리얼라이저를 수정했다.

serializers.py

from rest_framework import serializers
from .models import Book, Review
from taggit.serializers import TagListSerializerField, TaggitSerializer
from taggit.models import Tag


class ReviewSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField()
    book = serializers.SerializerMethodField()

    def get_author(self, obj):
        # print(obj["author_id"])
        return obj["author_id"]

    def get_book(self, obj):
        return obj["book_id"]

    class Meta:
        model = Review
        fields = "__all__"


class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = "__all__"


class BookTagSerializer(TaggitSerializer, serializers.ModelSerializer):
    # 태그 포함 시리얼라이저
    tags = TagListSerializerField()

    class Meta:
        model = Book
        fields = "__all__"


class ReviewCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Review
        fields = (
            "title",
            "content",
            "star",
        )


class BookSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField()
    category = serializers.SerializerMethodField()
    cover = serializers.SerializerMethodField()

    def get_author(self, obj):
        # print(obj["author_id"])
        return obj["author_id"]

    def get_category(self, obj):
        return obj["category_id"]

    def get_cover(self, obj):
        return obj["cover"]

    class Meta:
        model = Book
        fields = "__all__"

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.generics import get_object_or_404
from rest_framework import status, permissions
from .models import Book, Review, Author, TaggableManager
from .serializers import (
    BookSerializer,
    ReviewSerializer,
    BookTagSerializer,
    ReviewCreateSerializer,
    TagSerializer,
)
from taggit.serializers import TagListSerializerField, TaggitSerializer
from django.views.generic import TemplateView, ListView
from taggit.models import Tag


# Create your views here.
class Main(APIView):
    def get(self, request):
        # 추천 책
        books = Book.objects.all().order_by("likes").values()
        # values() 를 했기 때문에 값이 그대로 전달되지 않음 > serializerMethod 를 추가
        serializer = BookSerializer(books, many=True)

        # 인기 리뷰
        reviews = Review.objects.all().order_by("likes").values()

        re_serializer = ReviewSerializer(reviews, many=True)

        # 태그
        tags = Tag.objects.all()
        # print(tags)
        tag_serializer = TagSerializer(tags, many=True)

        serializer_list = [serializer.data, re_serializer.data, tag_serializer.data]

        content = {
            "status": 1,
            "responseCode": status.HTTP_200_OK,
            "data": serializer_list,
        }

        return Response(content)


class CategoryDetail(APIView):
    def get(self, request, category_id):
        books = Book.objects.filter(category_id=category_id).values()
        print(books)
        serializer = BookSerializer(books, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)


class BookDetail(APIView):
    def get(self, request, book_id):
        book = get_object_or_404(Book, id=book_id)
        serializer = BookTagSerializer(book)

        return Response(serializer.data, status=status.HTTP_200_OK)


class ReviewCreate(APIView):
    def post(self, request, book_id):
        if request.user.is_authenticated:
            serializer = ReviewCreateSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save(author=request.user, book_id=book_id)
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response("로그인 해주십시오", status=status.HTTP_403_FORBIDDEN)


class ReviewUpdate(APIView):
    def put(self, request, book_id, review_id):
        if request.user.is_authenticated:
            my_review = get_object_or_404(Review, id=review_id)
            if my_review.author == request.user:
                serializer = ReviewCreateSerializer(my_review, data=request.data)
                if serializer.is_valid():
                    serializer.save()
                    return Response("수정 완료", status=status.HTTP_200_OK)
                else:
                    return Response(
                        serializer.errors, status=status.HTTP_400_BAD_REQUEST
                    )
        else:
            return Response("권한이 없습니다.", status=status.HTTP_403_FORBIDDEN)

    def delete(self, request, book_id, review_id):
        my_review = get_object_or_404(Review, id=review_id)
        if my_review.author == request.user:
            my_review.delete()
            return Response("삭제 완료", status=status.HTTP_200_OK)
        else:
            return Response("권한이 없습니다.", status=status.HTTP_403_FORBIDDEN)


# html로 태그 전달
class TagCloudTV(TemplateView):
    # 모든 태그 추출
    template_name = "taggit/tag_cloud_view.html"


class TaggedObjectLV(ListView):
    # 특정 태그가 있는 책들
    template_name = "taggit/tag_with_book.html"
    model = Book

    def get_queryset(self):
        return Book.objects.filter(tags__name=self.kwargs.get("tags"))

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["tags"] = self.kwargs["tags"]
        return context
  • 메인페이지는 별도의 로그인 없이도 이용할 수 있으니 별도의 인증 처리를 넣지 않았고, 리뷰 고치기와 삭제는 is_authenticated 를 통해 인증된 사용자인지, 작성자와 request.user 가 같은 사람인지 확인한 다음 실행되도록 만들었다.

  • 책, 리뷰, 태그를 각각 다른 serializer 로 받아서 한 context 리스트에 넣은 다음 return 해줬다. html 에서 response 를 이용해 값을 출력해줄 예정이다.

포스트맨으로 헤더에 인증 토큰을 넣은 뒤 POST, GET, PUT, DELETE 요청을 모두 넣어본 결과 return 값은 제대로 나왔다.

profile
공부 중

0개의 댓글