From 4d0697953d9b606eab0797806fc51c3d961e8639 Mon Sep 17 00:00:00 2001 From: Denys Piuro Date: Mon, 30 Sep 2024 15:19:38 +0300 Subject: [PATCH] Fixed according to Stepan's remarks --- cinema/models.py | 3 +- cinema/serializers.py | 23 +++++------ cinema/views.py | 88 +++++++++++++++++++++++++++---------------- 3 files changed, 68 insertions(+), 46 deletions(-) diff --git a/cinema/models.py b/cinema/models.py index 2e7739f26..1454304c7 100644 --- a/cinema/models.py +++ b/cinema/models.py @@ -33,10 +33,9 @@ class Movie(models.Model): genres = models.ManyToManyField(Genre, related_name="movies") def save(self, *args, **kwargs): - actors = kwargs.pop("actors", None) - genres = kwargs.pop("genres", None) super().save(*args, **kwargs) + def set_related_fields(self, actors=None, genres=None): if actors is not None: self.actors.set(actors) if genres is not None: diff --git a/cinema/serializers.py b/cinema/serializers.py index 532aad77c..58cfb58c8 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -34,29 +34,30 @@ class MovieSerializer(serializers.Serializer): queryset=Genre.objects.all() ) - def create(self, validated_data): + def create(self, validated_data: dict) -> Movie: actors = validated_data.pop("actors", []) genres = validated_data.pop("genres", []) movie = Movie.objects.create(**validated_data) - movie.actors.set(actors) - movie.genres.set(genres) + movie.set_related_fields(actors=actors, genres=genres) return movie - def update(self, instance, validated_data): + def update(self, instance: Movie, validated_data: dict) -> Movie: actors = validated_data.pop("actors", None) genres = validated_data.pop("genres", None) - instance.title = validated_data.get("title", instance.title) + instance.title = validated_data.get( + "title", + instance.title + ) instance.description = validated_data.get( "description", instance.description ) - instance.duration = validated_data.get("duration", instance.duration) - - if actors is not None: - instance.actors.set(actors) - if genres is not None: - instance.genres.set(genres) + instance.duration = validated_data.get( + "duration", + instance.duration + ) + instance.set_related_fields(actors=actors, genres=genres) instance.save() return instance diff --git a/cinema/views.py b/cinema/views.py index 9ec2777c5..543b3a15c 100644 --- a/cinema/views.py +++ b/cinema/views.py @@ -1,8 +1,10 @@ from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.views import APIView -from rest_framework import status, generics, viewsets +from rest_framework import status, generics, viewsets, mixins from django.shortcuts import get_object_or_404 +from rest_framework.request import Request +from typing import Any from cinema.models import Movie, Genre, Actor, CinemaHall from cinema.serializers import ( @@ -14,7 +16,7 @@ @api_view(["GET", "POST"]) -def movie_list(request): +def movie_list(request: Request) -> Response: if request.method == "GET": movies = Movie.objects.all() serializer = MovieSerializer(movies, many=True) @@ -22,15 +24,13 @@ def movie_list(request): if request.method == "POST": serializer = MovieSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) @api_view(["GET", "PUT", "DELETE", "PATCH"]) -def movie_detail(request, pk): +def movie_detail(request: Request, pk: int) -> Response: movie = get_object_or_404(Movie, pk=pk) if request.method == "GET": @@ -40,11 +40,9 @@ def movie_detail(request, pk): if request.method in ["PUT", "PATCH"]: partial = request.method == "PATCH" serializer = MovieSerializer(movie, data=request.data, partial=partial) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_200_OK) - - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) if request.method == "DELETE": movie.delete() @@ -52,56 +50,80 @@ def movie_detail(request, pk): class GenreList(APIView): - def get(self, request): + def get(self, request: Request) -> Response: genres = Genre.objects.all() serializer = GenreSerializer(genres, many=True) return Response(serializer.data) - def post(self, request): + def post(self, request: Request) -> Response: serializer = GenreSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) class GenreDetail(APIView): - def get(self, request, pk): + def get(self, request: Request, pk: int) -> Response: genre = get_object_or_404(Genre, pk=pk) serializer = GenreSerializer(genre) return Response(serializer.data) - def put(self, request, pk): + def put(self, request: Request, pk: int) -> Response: genre = get_object_or_404(Genre, pk=pk) serializer = GenreSerializer(genre, data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data) - def patch(self, request, pk): + def patch(self, request: Request, pk: int) -> Response: genre = get_object_or_404(Genre, pk=pk) serializer = GenreSerializer(genre, data=request.data, partial=True) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_200_OK) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) - def delete(self, request, pk): + def delete(self, request: Request, pk: int) -> Response: genre = get_object_or_404(Genre, pk=pk) genre.delete() return Response(status=status.HTTP_204_NO_CONTENT) -class ActorList(generics.ListCreateAPIView): +class ActorList( + mixins.ListModelMixin, + mixins.CreateModelMixin, + generics.GenericAPIView +): queryset = Actor.objects.all() serializer_class = ActorSerializer + def get(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.list(request, *args, **kwargs) + + def post(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.create(request, *args, **kwargs) -class ActorDetail(generics.RetrieveUpdateDestroyAPIView): + +class ActorDetail( + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + mixins.DestroyModelMixin, + generics.GenericAPIView +): queryset = Actor.objects.all() serializer_class = ActorSerializer + def get(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.retrieve(request, *args, **kwargs) + + def put(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.update(request, *args, **kwargs) + + def patch(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.partial_update(request, *args, **kwargs) + + def delete(self, request: Request, *args: Any, **kwargs: Any) -> Response: + return self.destroy(request, *args, **kwargs) + class CinemaHallViewSet( viewsets.GenericViewSet,