From 2e02370ee386b34f858f73e79dfe3d14be123d2e Mon Sep 17 00:00:00 2001 From: Oksana Boliziuk Date: Fri, 20 Dec 2024 11:28:52 +0200 Subject: [PATCH 1/3] Solution --- cinema/serializers.py | 86 +++++++++++++++++++++++++++- cinema/tests/test_cinema_hall_api.py | 4 ++ cinema/urls.py | 28 ++++++++- cinema/views.py | 66 ++++++++++++++++++++- cinema_service/settings.py | 6 ++ cinema_service/urls.py | 10 +++- 6 files changed, 196 insertions(+), 4 deletions(-) diff --git a/cinema/serializers.py b/cinema/serializers.py index 612ca7e2..8489f331 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -1 +1,85 @@ -# write serializers here +from rest_framework import serializers +from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession + + +class ActorSerializer(serializers.ModelSerializer): + full_name = serializers.SerializerMethodField() + + class Meta: + model = Actor + fields = ("id", "first_name", "last_name", "full_name") + + def get_full_name(self, obj): + return f"{obj.first_name} {obj.last_name}" + + +class GenreSerializer(serializers.ModelSerializer): + class Meta: + model = Genre + fields = ("id", "name") + + +class BaseMovieSerializer(serializers.ModelSerializer): + class Meta: + model = Movie + fields = ("id", "title", "description", "duration", "genres", "actors") + + +class MovieListSerializer(BaseMovieSerializer): + genres = serializers.SlugRelatedField( + many=True, + read_only=True, + slug_field="name" + ) + actors = serializers.SerializerMethodField() + + def get_actors(self, obj): + return [ + f"{actor.first_name} {actor.last_name}" + for actor in obj.actors.all() + ] + + +class MovieRetrieveSerializer(BaseMovieSerializer): + genres = GenreSerializer(many=True) + actors = ActorSerializer(many=True) + + +class CinemaHallSerializer(serializers.ModelSerializer): + class Meta: + model = CinemaHall + fields = ("id", "name", "rows", "seats_in_row", "capacity") + + +class MovieSessionSerializer(serializers.ModelSerializer): + + class Meta: + model = MovieSession + fields = ("id", "show_time", "movie", "cinema_hall") + + +class MovieSessionListSerializer(MovieSessionSerializer): + movie_title = serializers.SlugRelatedField( + source="movie", slug_field="title", read_only=True + ) + cinema_hall_name = serializers.SlugRelatedField( + source="cinema_hall", slug_field="name", read_only=True + ) + cinema_hall_capacity = serializers.SlugRelatedField( + source="cinema_hall", slug_field="capacity", read_only=True + ) + + class Meta: + model = MovieSession + fields = ( + "id", + "show_time", + "movie_title", + "cinema_hall_name", + "cinema_hall_capacity", + ) + + +class MovieSessionRetrieveSerializer(MovieSessionSerializer): + movie = MovieListSerializer() + cinema_hall = CinemaHallSerializer() diff --git a/cinema/tests/test_cinema_hall_api.py b/cinema/tests/test_cinema_hall_api.py index d3e9ea77..518f2323 100644 --- a/cinema/tests/test_cinema_hall_api.py +++ b/cinema/tests/test_cinema_hall_api.py @@ -116,9 +116,13 @@ def test_patch_cinema_hall(self): self.assertEqual(CinemaHall.objects.get(id=1).name, "Green") def test_delete_cinema_hall(self): + print("Before DELETE request:", CinemaHall.objects.all()) response = self.client.delete( "/api/cinema/cinema_halls/1/", ) + print("After DELETE request:", CinemaHall.objects.all()) # Друкуємо всі об'єкти + print("Count of CinemaHall with id=1:", + CinemaHall.objects.filter(id=1).count()) # Друкуємо кількість об'єктів з id=1 db_cinema_halls_id_1 = CinemaHall.objects.filter(id=1) self.assertEqual(db_cinema_halls_id_1.count(), 0) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) diff --git a/cinema/urls.py b/cinema/urls.py index 420f8e8c..a00352be 100644 --- a/cinema/urls.py +++ b/cinema/urls.py @@ -1 +1,27 @@ -# write urls here +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from .views import ( + GenreViewSet, + ActorViewSet, + CinemaHallViewSet, + MovieViewSet, + MovieSessionViewSet, +) + +router = DefaultRouter() +router.register(r"genres", GenreViewSet, basename="genre") +router.register("actors", ActorViewSet, basename="actor") +router.register("cinema_halls", CinemaHallViewSet, basename="cinema_hall") +router.register("movies", MovieViewSet, basename="movie") +router.register( + "movie_sessions", + MovieSessionViewSet, + basename="movie_session" +) + + +urlpatterns = [ + path("", include(router.urls)), +] + +app_name = "cinema" diff --git a/cinema/views.py b/cinema/views.py index ae87bfde..de6aa5b0 100644 --- a/cinema/views.py +++ b/cinema/views.py @@ -1 +1,65 @@ -# write views here +from rest_framework import viewsets +from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession +from cinema.serializers import ( + GenreSerializer, + ActorSerializer, + CinemaHallSerializer, + MovieSessionSerializer, + MovieSessionListSerializer, + MovieListSerializer, + MovieRetrieveSerializer, + MovieSessionRetrieveSerializer, + BaseMovieSerializer, +) + + +class GenreViewSet(viewsets.ModelViewSet): + queryset = Genre.objects.all() + serializer_class = GenreSerializer + + +class ActorViewSet(viewsets.ModelViewSet): + queryset = Actor.objects.all() + serializer_class = ActorSerializer + + +class CinemaHallViewSet(viewsets.ModelViewSet): + queryset = CinemaHall.objects.all() + serializer_class = CinemaHallSerializer + + +class MovieViewSet(viewsets.ModelViewSet): + queryset = Movie.objects.prefetch_related("genres", "actors") + + def get_serializer_class(self): + if self.action == "list": + return MovieListSerializer + elif self.action == "retrieve": + return MovieRetrieveSerializer + return BaseMovieSerializer + + def get_queryset(self): + queryset = self.queryset + if self.action == "list": + return queryset.prefetch_related("genres", "actors") + return queryset + + +class MovieSessionViewSet(viewsets.ModelViewSet): + queryset = MovieSession.objects.all().select_related( + "movie", + "cinema_hall" + ) + + def get_serializer_class(self): + if self.action == "list": + return MovieSessionListSerializer + elif self.action == "retrieve": + return MovieSessionRetrieveSerializer + return MovieSessionSerializer + + def get_queryset(self): + queryset = self.queryset + if self.action == "list": + return queryset.select_related("movie", "cinema_hall") + return queryset diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 4b981921..6a3a572a 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -40,12 +40,14 @@ "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", + "debug_toolbar", "cinema", "user", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "debug_toolbar.middleware.DebugToolbarMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -131,3 +133,7 @@ # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +INTERNAL_IPS = [ + "127.0.0.1", +] diff --git a/cinema_service/urls.py b/cinema_service/urls.py index 083932c6..299dfe65 100644 --- a/cinema_service/urls.py +++ b/cinema_service/urls.py @@ -1,6 +1,14 @@ +from django.conf import settings from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), + path("api/cinema/", include("cinema.urls")), ] + +if settings.DEBUG: + import debug_toolbar + urlpatterns += [ + path("__debug__/", include(debug_toolbar.urls)), + ] From 199abb86ed1f1aa788f305afa7bd1b218290c165 Mon Sep 17 00:00:00 2001 From: Oksana Boliziuk Date: Fri, 20 Dec 2024 11:39:30 +0200 Subject: [PATCH 2/3] Remove unnecessary print statements, adjust SlugRelatedField usage, and update debug settings for better clarity, security, and maintainability. --- cinema/serializers.py | 2 +- cinema/tests/test_cinema_hall_api.py | 4 ---- cinema_service/settings.py | 2 -- db.sqlite3 | Bin 0 -> 225280 bytes 4 files changed, 1 insertion(+), 7 deletions(-) create mode 100644 db.sqlite3 diff --git a/cinema/serializers.py b/cinema/serializers.py index 8489f331..e432566f 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -65,7 +65,7 @@ class MovieSessionListSerializer(MovieSessionSerializer): cinema_hall_name = serializers.SlugRelatedField( source="cinema_hall", slug_field="name", read_only=True ) - cinema_hall_capacity = serializers.SlugRelatedField( + cinema_hall_capacity = serializers.ReadOnlyField( source="cinema_hall", slug_field="capacity", read_only=True ) diff --git a/cinema/tests/test_cinema_hall_api.py b/cinema/tests/test_cinema_hall_api.py index 518f2323..d3e9ea77 100644 --- a/cinema/tests/test_cinema_hall_api.py +++ b/cinema/tests/test_cinema_hall_api.py @@ -116,13 +116,9 @@ def test_patch_cinema_hall(self): self.assertEqual(CinemaHall.objects.get(id=1).name, "Green") def test_delete_cinema_hall(self): - print("Before DELETE request:", CinemaHall.objects.all()) response = self.client.delete( "/api/cinema/cinema_halls/1/", ) - print("After DELETE request:", CinemaHall.objects.all()) # Друкуємо всі об'єкти - print("Count of CinemaHall with id=1:", - CinemaHall.objects.filter(id=1).count()) # Друкуємо кількість об'єктів з id=1 db_cinema_halls_id_1 = CinemaHall.objects.filter(id=1) self.assertEqual(db_cinema_halls_id_1.count(), 0) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 6a3a572a..fa8aec17 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -40,14 +40,12 @@ "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", - "debug_toolbar", "cinema", "user", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", - "debug_toolbar.middleware.DebugToolbarMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..f2680c1e12a3cd2464eae9816c4bd487301666e4 GIT binary patch literal 225280 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 literal 0 HcmV?d00001 From 5adb1da8531b963421a05daf49f3345dad02b4ab Mon Sep 17 00:00:00 2001 From: Oksana Boliziuk Date: Fri, 20 Dec 2024 12:13:36 +0200 Subject: [PATCH 3/3] Correct usage of ReadOnlyField in MovieSessionListSerializer. --- cinema/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cinema/serializers.py b/cinema/serializers.py index e432566f..6bc478a1 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -66,7 +66,7 @@ class MovieSessionListSerializer(MovieSessionSerializer): source="cinema_hall", slug_field="name", read_only=True ) cinema_hall_capacity = serializers.ReadOnlyField( - source="cinema_hall", slug_field="capacity", read_only=True + source="cinema_hall.capacity" ) class Meta: