Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #737

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 73 additions & 3 deletions cinema/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from rest_framework import serializers

from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession
from cinema.models import (
Genre,
Actor,
CinemaHall,
Movie,
MovieSession,
Ticket,
Order
)


class GenreSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -46,9 +54,25 @@ class Meta:


class MovieSessionSerializer(serializers.ModelSerializer):
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", "cinema_hall")
fields = (
"id",
"show_time",
"movie",
"cinema_hall",
"movie_title",
"cinema_hall_name",
"cinema_hall_capacity"
)


class MovieSessionListSerializer(MovieSessionSerializer):
Expand All @@ -59,6 +83,7 @@ class MovieSessionListSerializer(MovieSessionSerializer):
cinema_hall_capacity = serializers.IntegerField(
source="cinema_hall.capacity", read_only=True
)
tickets_available = serializers.IntegerField(read_only=True)

class Meta:
model = MovieSession
Expand All @@ -68,13 +93,58 @@ class Meta:
"movie_title",
"cinema_hall_name",
"cinema_hall_capacity",
"tickets_available",
)


class TicketSerializer(serializers.ModelSerializer):
movie_session = MovieSessionSerializer(read_only=True)

class Meta:
model = Ticket
fields = ("id", "row", "seat", "movie_session")

def validate(self, data):
data = super().validate(data)
Comment on lines +107 to +108

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The super().validate(data) call in the validate method of TicketSerializer is incorrect. The validate method should not call super().validate(data) because ModelSerializer does not have a validate method that takes data as an argument. Consider removing this line or adjusting it to properly validate the data.

ticket = Ticket(
movie_session=data.get("movie_session"),
row=data.get("row"),
seat=data.get("seat"),
)
ticket.full_clean()
return data


class TicketRowSeatSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = ("row", "seat")


class MovieSessionDetailSerializer(MovieSessionSerializer):
movie = MovieListSerializer(many=False, read_only=True)
cinema_hall = CinemaHallSerializer(many=False, read_only=True)
taken_places = TicketRowSeatSerializer(
many=True,
read_only=True,
source="tickets"
)

class Meta:
model = MovieSession
fields = ("id", "show_time", "movie", "cinema_hall")
fields = ("id", "show_time", "movie", "cinema_hall", "taken_places")


class OrderSerializer(serializers.ModelSerializer):
tickets = TicketSerializer(many=True, read_only=True, allow_null=False)

class Meta:
model = Order
fields = ("id", "created_at", "tickets")

def create(self, validated_data):
tickets_data = validated_data.pop("tickets")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The create method in OrderSerializer attempts to pop 'tickets' from validated_data, but 'tickets' is marked as read_only=True in the serializer, meaning it won't be present in validated_data. This will raise a KeyError. Consider revising this logic to handle the creation of tickets appropriately.

order = Order.objects.create(**validated_data)
for ticket_data in tickets_data:
Ticket.objects.create(order=order, **ticket_data)
return order
4 changes: 4 additions & 0 deletions cinema/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
CinemaHallViewSet,
MovieViewSet,
MovieSessionViewSet,
OrderViewSet,
TicketViewSet
)

router = routers.DefaultRouter()
Expand All @@ -15,6 +17,8 @@
router.register("cinema_halls", CinemaHallViewSet)
router.register("movies", MovieViewSet)
router.register("movie_sessions", MovieSessionViewSet)
router.register("orders", OrderViewSet)
router.register("tickets", TicketViewSet)

urlpatterns = [path("", include(router.urls))]

Expand Down
107 changes: 100 additions & 7 deletions cinema/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
from rest_framework import viewsets
import re
from rest_framework.response import Response

from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession
from django.db.models import Count, F
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination
from datetime import datetime
from cinema.models import (
Genre,
Actor,
CinemaHall,
Movie,
MovieSession,
Order,
Ticket
)

from cinema.serializers import (
GenreSerializer,
Expand All @@ -12,26 +25,40 @@
MovieDetailSerializer,
MovieSessionDetailSerializer,
MovieListSerializer,
OrderSerializer,
TicketSerializer
)


class GenreViewSet(viewsets.ModelViewSet):
queryset = Genre.objects.all()
serializer_class = GenreSerializer

def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

sofiiasavkova marked this conversation as resolved.
Show resolved Hide resolved

class ActorViewSet(viewsets.ModelViewSet):
queryset = Actor.objects.all()
serializer_class = ActorSerializer

def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

sofiiasavkova marked this conversation as resolved.
Show resolved Hide resolved

class CinemaHallViewSet(viewsets.ModelViewSet):
queryset = CinemaHall.objects.all()
serializer_class = CinemaHallSerializer

pagination_class = None


class MovieViewSet(viewsets.ModelViewSet):
queryset = Movie.objects.all()
queryset = Movie.objects.prefetch_related("genres", "actors")
serializer_class = MovieSerializer

def get_serializer_class(self):
Expand All @@ -43,16 +70,82 @@ def get_serializer_class(self):

return MovieSerializer

def get_queryset(self):
queryset = super().get_queryset()

title = self.request.query_params.get("title", None)
actors = self.request.query_params.get("actors", None)
genres = self.request.query_params.get("genres", None)

if title:
queryset = queryset.filter(title__icontains=title)

if genres:
genres_ids = [int(str_id) for str_id in genres.split(",")]
queryset = queryset.filter(genres__in=genres_ids)

if actors:
actors_ids = [int(str_id) for str_id in actors.split(",")]
queryset = queryset.filter(actors__in=actors_ids)

return queryset.distinct()

def paginate_queryset(self, queryset):
return None

sofiiasavkova marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +93 to +94

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paginate_queryset method in MovieViewSet returns None, which disables pagination. If pagination is required, consider using the default pagination or a custom pagination class instead of returning None.


class MovieSessionViewSet(viewsets.ModelViewSet):
queryset = MovieSession.objects.all()
queryset = MovieSession.objects.select_related("movie", "cinema_hall")
serializer_class = MovieSessionSerializer

pagination_class = None

def get_serializer_class(self):
if self.action == "list":
return MovieSessionListSerializer

if self.action == "retrieve":
elif self.action == "retrieve":
return MovieSessionDetailSerializer

return MovieSessionSerializer

def get_queryset(self):
queryset = super().get_queryset()

movie = self.request.query_params.get("movie")
if movie:
queryset = queryset.filter(movie__id=movie)

date = self.request.query_params.get("date")
if date:
try:
date_obj = datetime.strptime(date, "%Y-%m-%d").date()
queryset = queryset.filter(show_time__date=date_obj)
except ValueError:
return queryset.none()

queryset = queryset.annotate(
tickets_available=(
F("cinema_hall__rows") * F("cinema_hall__seats_in_row")
- Count("tickets")
)
).order_by("id")

return queryset.distinct()


class OrderPagination(PageNumberPagination):
page_size = 5


class OrderListCreateView(viewsets.ModelViewSet):
pagination_class = OrderPagination

Comment on lines +139 to +140

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OrderListCreateView class is defined but lacks implementation details such as queryset and serializer_class. Ensure that this class is fully implemented if it is intended to be used.


class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
pagination_class = OrderPagination


class TicketViewSet(viewsets.ModelViewSet):
queryset = Ticket.objects.all()
serializer_class = TicketSerializer
7 changes: 7 additions & 0 deletions cinema_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,10 @@
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": (
"rest_framework.pagination.PageNumberPagination"
),
"PAGE_SIZE": 5,
}
Loading