Skip to content

Commit

Permalink
"solution"
Browse files Browse the repository at this point in the history
  • Loading branch information
Olha Stadnik committed Dec 14, 2024
1 parent efd4b75 commit 8d777cc
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 27 deletions.
6 changes: 4 additions & 2 deletions cinema/migrations/0002_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ class Migration(migrations.Migration):
model_name="order",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="moviesession",
name="cinema_hall",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="cinema.cinemahall"
on_delete=django.db.models.deletion.CASCADE,
to="cinema.cinemahall",
),
),
migrations.AddField(
Expand Down
6 changes: 3 additions & 3 deletions cinema/migrations/0003_movie_duration.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
class Migration(migrations.Migration):

dependencies = [
('cinema', '0002_initial'),
("cinema", "0002_initial"),
]

operations = [
migrations.AddField(
model_name='movie',
name='duration',
model_name="movie",
name="duration",
field=models.IntegerField(default=123),
preserve_default=False,
),
Expand Down
6 changes: 3 additions & 3 deletions cinema/migrations/0004_alter_genre_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
class Migration(migrations.Migration):

dependencies = [
('cinema', '0003_movie_duration'),
("cinema", "0003_movie_duration"),
]

operations = [
migrations.AlterField(
model_name='genre',
name='name',
model_name="genre",
name="name",
field=models.CharField(max_length=255, unique=True),
),
]
58 changes: 56 additions & 2 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,
Order,
Ticket,
)


class GenreSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -59,6 +67,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 +77,58 @@ class Meta:
"movie_title",
"cinema_hall_name",
"cinema_hall_capacity",
"tickets_available",
)


class TicketSeatRowSerializer(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 = TicketSeatRowSerializer(
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 TicketSerializer(serializers.ModelSerializer):
movie_session = MovieSessionListSerializer(many=False, read_only=True)

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

def validate(self, data):
data = super(TicketSerializer).validate(data)
ticket = Ticket(
movie_session=data.get("movie_session"),
row=data.get("row"),
seat=data.get("seat"),
)
ticket.full_clean()
return data


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")
order = Order.objects.create(**validated_data)
for ticket_data in tickets_data:
Ticket.objects.create(order=order, **ticket_data)
return order
7 changes: 1 addition & 6 deletions cinema/tests/test_movie_session_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ def setUp(self):
self.movie_session = MovieSession.objects.create(
movie=self.movie,
cinema_hall=self.cinema_hall,
show_time=datetime.datetime(
year=2022,
month=9,
day=2,
hour=9
),
show_time=datetime.datetime(year=2022, month=9, day=2, hour=9),
)

def test_get_movie_sessions(self):
Expand Down
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
80 changes: 78 additions & 2 deletions cinema/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
from django.db.models import Count, F
from rest_framework import viewsets

from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession
from rest_framework.pagination import PageNumberPagination

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

from cinema.serializers import (
GenreSerializer,
Expand All @@ -12,6 +22,8 @@
MovieDetailSerializer,
MovieSessionDetailSerializer,
MovieListSerializer,
OrderSerializer,
TicketSerializer,
)


Expand Down Expand Up @@ -43,6 +55,28 @@ def get_serializer_class(self):

return MovieSerializer

def get_queryset(self):
queryset = super().get_queryset()
if self.action == ("list", "retrieve"):
queryset = self.queryset.prefetch_related("actors", "genres")

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

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

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

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

return queryset.distinct()


class MovieSessionViewSet(viewsets.ModelViewSet):
queryset = MovieSession.objects.all()
Expand All @@ -56,3 +90,45 @@ def get_serializer_class(self):
return MovieSessionDetailSerializer

return MovieSessionSerializer

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

if self.action == "retrieve":
queryset = queryset.select_related("movie")

elif self.action == "list":
queryset = (
queryset.select_related("cinema_hall").annotate(
tickets_available=(
F("cinema_hall__rows") * F("cinema_hall__seats_in_row")
- Count("tickets")
)
)
).order_by("id")

movie = self.request.query_params.get("movie")
date = self.request.query_params.get("date")

if movie:
queryset = queryset.filter(movie__id=movie)

if date:
queryset = queryset.filter(show_time__date=date)

return queryset.distinct()


class TicketViewSet(viewsets.ModelViewSet):
queryset = Ticket.objects.all()
serializer_class = TicketSerializer


class OrderPagination(PageNumberPagination):
page_size = 5


class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
pagination_class = OrderPagination
13 changes: 4 additions & 9 deletions cinema_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = (
"django-insecure-6vubhk2$++agnctay_4pxy_8cq)mosmn(*-#2b^v4cgsh-^!i3"
)
SECRET_KEY = "django-insecure-6vubhk2$++agnctay_4pxy_8cq)mosmn(*-#2b^v4cgsh-^!i3"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
Expand Down Expand Up @@ -100,16 +98,13 @@
"UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation."
"MinimumLengthValidator",
"NAME": "django.contrib.auth.password_validation." "MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation."
"CommonPasswordValidator",
"NAME": "django.contrib.auth.password_validation." "CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation."
"NumericPasswordValidator",
"NAME": "django.contrib.auth.password_validation." "NumericPasswordValidator",
},
]

Expand Down

0 comments on commit 8d777cc

Please sign in to comment.