From 7f236d7fa522ff4815be7fae7a3c76e779166205 Mon Sep 17 00:00:00 2001 From: Volodymyr Date: Wed, 11 Dec 2024 16:06:28 +0200 Subject: [PATCH 1/3] solution --- cinema/models.py | 14 ++++--- cinema/serializers.py | 81 +++++++++++++++++++++++++++++++++++++- cinema/urls.py | 24 ++++++++++- cinema/views.py | 61 +++++++++++++++++++++++++++- cinema_service/settings.py | 2 +- cinema_service/urls.py | 3 +- 6 files changed, 174 insertions(+), 11 deletions(-) diff --git a/cinema/models.py b/cinema/models.py index c42d2a3d..7724fd64 100644 --- a/cinema/models.py +++ b/cinema/models.py @@ -27,6 +27,10 @@ class Actor(models.Model): first_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255) + @property + def full_name(self): + return f"{self.first_name} {self.last_name}" + def __str__(self): return self.first_name + " " + self.last_name @@ -85,16 +89,14 @@ def clean(self): (self.row, "row", "count_rows"), (self.seat, "seat", "count_seats_in_row"), ]: - count_attrs = getattr( - self.movie_session.cinema_hall, cinema_hall_attr_name - ) + count_attrs = getattr(self.movie_session.cinema_hall, cinema_hall_attr_name) if not (1 <= ticket_attr_value <= count_attrs): raise ValidationError( { ticket_attr_name: f"{ticket_attr_name} number " - f"must be in available range: " - f"(1, {cinema_hall_attr_name}): " - f"(1, {count_attrs})" + f"must be in available range: " + f"(1, {cinema_hall_attr_name}): " + f"(1, {count_attrs})" } ) diff --git a/cinema/serializers.py b/cinema/serializers.py index 612ca7e2..8923dc4e 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -1 +1,80 @@ -# write serializers here +from rest_framework import serializers +from cinema.models import CinemaHall, Genre, Actor, Movie, MovieSession + + +class CinemaHallSerializer(serializers.ModelSerializer): + class Meta: + model = CinemaHall + fields = ("id", "name", "rows", "seats_in_row", "capacity") + + +class GenreSerializer(serializers.ModelSerializer): + class Meta: + model = Genre + fields = ("id", "name") + + +class ActorSerializer(serializers.ModelSerializer): + class Meta: + model = Actor + fields = ("id", "first_name", "last_name", "full_name") + + +class MovieSerializer(serializers.ModelSerializer): + class Meta: + model = Movie + fields = ("id", "title", "description", "duration", "genres", "actors") + + +class MovieListSerializer(MovieSerializer): + genres = serializers.SlugRelatedField( + many=True, + read_only=True, + slug_field="name" + ) + actors = serializers.SlugRelatedField( + many=True, + read_only=True, + slug_field="full_name" + ) + + +class MovieDetailSerializer(MovieSerializer): + genres = GenreSerializer(many=True, read_only=True) + actors = ActorSerializer(many=True, read_only=True) + + +class MovieSessionSerializer(serializers.ModelSerializer): + movie = serializers.PrimaryKeyRelatedField(queryset=Movie.objects.all()) + cinema_hall = serializers.PrimaryKeyRelatedField(queryset=CinemaHall.objects.all()) + class Meta: + model = MovieSession + fields = ("show_time", "movie", "cinema_hall") + + +class MovieSessionListSerializer(MovieSessionSerializer): + movie_title = serializers.CharField( + source="movie.title", + read_only=True + ) + cinema_hall_name = serializers.CharField( + source="cinema_hall.name", + read_only=True + ) + cinema_hall_capacity = serializers.IntegerField( + source="cinema_hall.capacity", + read_only=True + ) + + class Meta: + model = MovieSession + fields = ( + "id", "show_time", + "movie_title", "cinema_hall_name", + "cinema_hall_capacity" + ) + + +class MovieSessionDetailSerializer(MovieSessionSerializer): + movie = MovieListSerializer(many=False, read_only=True) + cinema_hall = CinemaHallSerializer(many=False, read_only=True) diff --git a/cinema/urls.py b/cinema/urls.py index 420f8e8c..581af4f2 100644 --- a/cinema/urls.py +++ b/cinema/urls.py @@ -1 +1,23 @@ -# write urls here +from django.urls import path, include +from rest_framework import routers + +from cinema.views import ( + CinemaHallViewSet, + GenreViewSet, + ActorViewSet, + MovieViewSet, + MovieSessionViewSet +) + +router = routers.DefaultRouter() +router.register("cinema_halls", CinemaHallViewSet) +router.register("genres", GenreViewSet) +router.register("actors", ActorViewSet) +router.register("movies", MovieViewSet, basename="movie") +router.register("movie_sessions", MovieSessionViewSet, basename="movie_session") + +urlpatterns = [ + path("", include(router.urls)) +] + +app_name = "cinema" \ No newline at end of file diff --git a/cinema/views.py b/cinema/views.py index ae87bfde..a85d8ca9 100644 --- a/cinema/views.py +++ b/cinema/views.py @@ -1 +1,60 @@ -# write views here +from rest_framework import viewsets +from cinema.models import CinemaHall, Genre, Actor, Movie, MovieSession +from cinema.serializers import ( + CinemaHallSerializer, GenreSerializer, + ActorSerializer, MovieSerializer, + MovieSessionSerializer, MovieListSerializer, + MovieDetailSerializer, MovieSessionListSerializer, + MovieSessionDetailSerializer +) + + +class CinemaHallViewSet(viewsets.ModelViewSet): + queryset = CinemaHall.objects.all() + serializer_class = CinemaHallSerializer + + +class GenreViewSet(viewsets.ModelViewSet): + queryset = Genre.objects.all() + serializer_class = GenreSerializer + + +class ActorViewSet(viewsets.ModelViewSet): + queryset = Actor.objects.all() + serializer_class = ActorSerializer + + +class MovieViewSet(viewsets.ModelViewSet): + queryset = Movie.objects.all() + serializer_class = MovieSerializer + + def get_queryset(self): + queryset = self.queryset + if self.action in ("list", "retrieve"): + return queryset.prefetch_related("genres", "actors") + return queryset + + def get_serializer_class(self): + if self.action == "list": + return MovieListSerializer + if self.action == "retrieve": + return MovieDetailSerializer + return MovieSerializer + + +class MovieSessionViewSet(viewsets.ModelViewSet): + queryset = MovieSession.objects.all() + serializer_class = MovieSessionSerializer + + def get_queryset(self): + queryset = self.queryset + if self.action == "list": + return queryset.select_related("movie", "cinema_hall") + return queryset + + def get_serializer_class(self): + if self.action == "list": + return MovieSessionListSerializer + if self.action == "retrieve": + return MovieSessionDetailSerializer + return MovieSessionSerializer diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 4b981921..08a656f6 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -119,7 +119,7 @@ USE_I18N = True -USE_TZ = True +USE_TZ = False # Static files (CSS, JavaScript, Images) diff --git a/cinema_service/urls.py b/cinema_service/urls.py index 083932c6..229767ed 100644 --- a/cinema_service/urls.py +++ b/cinema_service/urls.py @@ -1,6 +1,7 @@ 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", namespace="cinema")), ] From 8c8adfa194802fa3d3ff6f83187c423aa7e62d30 Mon Sep 17 00:00:00 2001 From: Volodymyr Date: Wed, 11 Dec 2024 16:12:29 +0200 Subject: [PATCH 2/3] flake --- cinema/models.py | 10 ++++++---- cinema/serializers.py | 5 ++++- cinema/urls.py | 8 ++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cinema/models.py b/cinema/models.py index 7724fd64..56922020 100644 --- a/cinema/models.py +++ b/cinema/models.py @@ -89,14 +89,16 @@ def clean(self): (self.row, "row", "count_rows"), (self.seat, "seat", "count_seats_in_row"), ]: - count_attrs = getattr(self.movie_session.cinema_hall, cinema_hall_attr_name) + count_attrs = getattr( + self.movie_session.cinema_hall, cinema_hall_attr_name + ) if not (1 <= ticket_attr_value <= count_attrs): raise ValidationError( { ticket_attr_name: f"{ticket_attr_name} number " - f"must be in available range: " - f"(1, {cinema_hall_attr_name}): " - f"(1, {count_attrs})" + f"must be in available range: " + f"(1, {cinema_hall_attr_name}): " + f"(1, {count_attrs})" } ) diff --git a/cinema/serializers.py b/cinema/serializers.py index 8923dc4e..a929eab6 100644 --- a/cinema/serializers.py +++ b/cinema/serializers.py @@ -46,7 +46,10 @@ class MovieDetailSerializer(MovieSerializer): class MovieSessionSerializer(serializers.ModelSerializer): movie = serializers.PrimaryKeyRelatedField(queryset=Movie.objects.all()) - cinema_hall = serializers.PrimaryKeyRelatedField(queryset=CinemaHall.objects.all()) + cinema_hall = (serializers. + PrimaryKeyRelatedField + (queryset=CinemaHall.objects.all())) + class Meta: model = MovieSession fields = ("show_time", "movie", "cinema_hall") diff --git a/cinema/urls.py b/cinema/urls.py index 581af4f2..f37fdd7b 100644 --- a/cinema/urls.py +++ b/cinema/urls.py @@ -14,10 +14,14 @@ router.register("genres", GenreViewSet) router.register("actors", ActorViewSet) router.register("movies", MovieViewSet, basename="movie") -router.register("movie_sessions", MovieSessionViewSet, basename="movie_session") +router.register( + "movie_sessions", + MovieSessionViewSet, + basename="movie_session" +) urlpatterns = [ path("", include(router.urls)) ] -app_name = "cinema" \ No newline at end of file +app_name = "cinema" From fe70ff0f50d13aba7657c5ec07cf3e048e49fcc8 Mon Sep 17 00:00:00 2001 From: Volodymyr Date: Wed, 11 Dec 2024 16:51:42 +0200 Subject: [PATCH 3/3] fix --- cinema_service/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 08a656f6..4b981921 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -119,7 +119,7 @@ USE_I18N = True -USE_TZ = False +USE_TZ = True # Static files (CSS, JavaScript, Images)