Skip to content
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
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Dockerfile
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose.yaml uses service names cinema and db but task requires services named app and db, and that app always waits for db using a wait_for_db management command. The compose file runs python manage.py wait_for_db but service is cinema, not app. Rename service to app to match checklist.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose.yaml maps db volume my_db:$PGDATA — using $PGDATA in compose may expand to empty inside compose; typically use - my_db:/var/lib/postgresql/data or use the PGDATA env var defined in .env. Verify .env sets PGDATA; otherwise volume mapping will be incorrect and DB persistence may break.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

settings.py (DATABASES) still uses sqlite3. To meet the requirement to switch to PostgreSQL via official image, settings must be updated to read DB_HOST, DB_NAME, DB_USER, DB_PASSWORD, DB_PORT from environment and use django.db.backends.postgresql engine. Without this change, the project won't use Postgres container.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There is no wait_for_db management command file present in repository. The docker-compose references python manage.py wait_for_db but the required management command implementation is missing — implement a custom Django management command that polls the DB until available as required by task.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose maps app ports as "8001:8000"; combined with the requirement that API be at 127.0.0.1:8000, this is inconsistent. Change to "8000:8000" to meet the check instructions.

docker-compose.yml
Comment on lines +1 to +2
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL - Checklist item #12: Service must be named app in docker-compose, but is named cinema. Change the service name from cinema: to app:.

venv/
Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.dockerignore currently lists only Dockerfile, docker-compose.yml, venv/. Consider adding pycache, *.pyc, .pytest_cache, .env, .git, media, and other unnecessary files to keep images thin as required.

Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The .dockerignore is minimal and misses recommended entries. Expand to ignore Python/Django artifacts and media per checklist (e.g. pycache/, *.pyc, .git/, .env, .pytest_cache/, media/). This was suggested in previous review.

Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

IMPORTANT - Checklist item #6: The .dockerignore is minimal. Expand it to exclude __pycache__/, *.pyc, .git/, .env, .pytest_cache/, media/, and any local venv/ to keep Docker images thin and prevent secrets from leaking.

19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.11.6-alpine3.18
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile doesn't install system dependencies required by Pillow (build tools, libjpeg, zlib). Without these, image upload/tests will fail inside the Alpine image. Add apk packages such as build-base, libjpeg-turbo-dev, zlib-dev, jpeg-dev, musl-dev (and any others needed) before pip install.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose service is named cinema and maps host port 8001 to container 8000; the checklist requires the service be named app and expose host port 8000: change service name to app and ports to "8000:8000. Also ensure the app commandrunspython manage.py wait_for_db` before migrate and runserver as required.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The repo is missing the Django management command wait_for_db under a management/commands module. docker-compose relies on it to wait for Postgres; implement management/commands/wait_for_db.py that polls the DB and exits when available (using django.db.utils and time.sleep).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.dockerignore is very small. Expand to exclude __pycache__/, *.pyc, .git/, .env, .pytest_cache/, and media/ to keep images thin as requested by checklist.

LABEL maintainer="shafran.andriy@gmail.com"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The service name is cinema, but checklist items #12, #18, #19 require it to be named app. Rename this service to app.


ENV PYTHONUNBUFFERED=1
WORKDIR /app
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ports are mapped to "8001:8000", but checklist item #13 requires "8000:8000" so the API is reachable at 127.0.0.1:8000/api/.

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile does not install system dependencies required by pillow (used in tests for image creation). On Alpine you typically need build-base, jpeg-dev, zlib-dev, freetype-dev, lcms2-dev, openjpeg-dev, tiff-dev, libjpeg-turbo-dev, and musl-dev before pip install. Without them pip install pillow will likely fail. Add an apk add step before pip install.

Comment on lines +1 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile is missing Alpine system packages required for Pillow (build-base, libjpeg-turbo-dev, zlib-dev, jpeg-dev, musl-dev, musl-utils, libffi-dev, openssl-dev, cargo, rust). Without these, image uploads and related tests will fail during build or runtime.

COPY . .
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

COPY . . copies the entire repository including files that should be ignored by the image. Ensure .dockerignore is correct (see .dockerignore file includes only 3 lines, missing common entries like pycache, *.pyc, .git, .venv, env files, migrations if desired). Otherwise image will be larger and may leak sensitive files.

RUN mkdir -p /files/media
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You create directory /files/media and chown/chmod it, which is good, but MEDIA_ROOT in settings.py points to BASE_DIR / "media". The Dockerfile uses /files/media and docker-compose maps volume my_media to /files/media. This mismatch means Django will save uploaded files to a different path inside container than the volume; update MEDIA_ROOT to /files/media or change Dockerfile/volumes to match settings.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

MEDIA_ROOT must match the volume mount used in docker-compose (/files/media). I see settings.py already sets MEDIA_ROOT = "/files/media" — good. Ensure docker-compose mounts my_media:/files/media (compose file currently mounts /files/media) and Dockerfile creates/chowns that path — Dockerfile does create /files/media but ensure permissions set while root before switching user. Move package install and media dir creation earlier (before USER my_user) and ensure chown/chmod executed as root (they are currently root).


RUN adduser \
--disabled-password \
--no-create-home \
Comment on lines +11 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile uses Alpine Python image which is fine, but there's no explicit creation or copying of a non-root user home; using --no-create-home prevents creating home and may cause permission issues for package caches or migrations. Consider creating a home or using a dedicated app user with a home directory. Also ensure packages requiring build tools on Alpine (Pillow) are installed in requirements or add build dependencies (musl headers, gcc, libjpeg-dev) before pip install to avoid install failures in Docker.

my_user

RUN chown -R my_user:my_user /files/media
RUN chmod -R 755 /files/media

USER my_user
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Final USER my_user will run commands; however many operations during image build (collectstatic/migrations) may require root or correct permissions. Ensure that entrypoint commands run inside container with appropriate permissions. Also consider switching to non-root after any operations that require root are complete.

20 changes: 20 additions & 0 deletions cinema/management/commands/wait_for_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import time
from django.db import connections
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Service name must be app per checklist item #12, not cinema. Change cinema: to app: at the start of the service definition.

from django.db.utils import OperationalError
Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expand .dockerignore to include __pycache__/, *.pyc, .git/, .env, .pytest_cache/, media/, and *.sqlite3 to keep images thin and prevent secret leaks.

from django.core.management import BaseCommand

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Port mapping must be "8000:8000" per checklist item #13 so the API is accessible at 127.0.0.1:8000/api/. Change 8001 to 8000.


class Command(BaseCommand):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile must install Alpine system packages for Pillow before pip install. Add this RUN command before line 7: RUN apk add --no-cache --virtual .build-deps build-base libjpeg-turbo-dev zlib-dev jpeg-dev musl-dev

"""Django command to pause execution until db is available"""

def handle(self, *args, **options):
self.stdout.write("Waiting for database...")
db_conn = None
while not db_conn:
try:
db_conn = connections["default"]
except OperationalError:
self.stdout.write("Database unavailable, waiting 1 second...")
time.sleep(1)

self.stdout.write(self.style.SUCCESS("Database available!"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 6.0.4 on 2026-04-22 14:03
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I couldn't find implementation of wait_for_db management command in provided files. The task requires implementing a Django management command wait_for_db which repeatedly attempts DB connection. This is missing and must be added so app waits for DB during docker-compose up.


import django.db.models.deletion
Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.dockerignore is minimal and excludes only Dockerfile, docker-compose.yml and venv/. Consider adding pycache/, *.pyc, .git/, .env, .pytest_cache/, media/ and other large directories to make images thinner as required by checklist.

Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose.yaml uses service name cinema and maps host port 8001 to container 8000. The task requires the service to be named app and exposed on host port 8000 so API is available at 127.0.0.1:8000/api/. Rename service to app and change ports to "8000:8000".

Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dockerfile creates /files/media and sets ownership to my_user, but the image does not install Pillow build dependencies and also copies the entire repo (including venv) into image because .dockerignore is minimal. Improve .dockerignore to exclude __pycache__/, *.pyc, .git/, .env, .pytest_cache/, and media/ to produce thinner images and avoid leaking secrets.

from django.conf import settings
from django.db import migrations, models


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile does not install system packages required to build Pillow on Alpine (build-base, libjpeg-turbo-dev, zlib-dev, etc.). This will likely cause image upload/tests to fail. Add an APK install step before pip install, e.g. apk add --no-cache build-base libjpeg-turbo-dev zlib-dev jpeg-dev zlib (and any other needed libs).

Comment on lines +1 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Dockerfile uses python:3.11.6-alpine3.18 and then runs pip install -r requirements.txt as root but does not set up virtualenv or a non-root user before installing. Installer step is fine, but ensure system deps are installed before pip. Also consider using --no-cache for apk and cleaning apk cache to keep image thin.

Comment on lines +1 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing Alpine system packages required for Pillow (used for image handling). Add RUN apk add --no-cache --virtual .build-deps build-base libjpeg-turbo-dev zlib-dev jpeg-dev musl-dev before pip install, then RUN apk del .build-deps after, to prevent build failures and enable image uploading functionality required by the tests.

class Migration(migrations.Migration):
Comment on lines +1 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose command chains python manage.py makemigrations && python manage.py wait_for_db && python manage.py migrate && python manage.py runserver .... Running makemigrations in production run is unusual; migrations should be created during development, not at container start. It isn't strictly required by task but might be undesirable; consider removing makemigrations to avoid unexpected migration files being generated at runtime.

Comment on lines +1 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dockerfile uses python:3.11.6-alpine which is good for thin image, but it copies entire project (COPY . .) after installing requirements while also mounting the host volume ./:/app in docker-compose; this will override installed dependencies or built files and can cause permission mismatches (user my_user created). Consider copying only necessary files and avoid conflicting volume during development, or set proper permissions.

Comment on lines +1 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests expect the API to be available at 127.0.0.1:8000/api/ and use image uploads; ensure runserver is bound to 0.0.0.0:8000 (done) and host port mapping is 8000:8000. Also ensure MEDIA_ROOT and media volume mapping align so tests that check os.path.exists(movie.image.path) succeed.


Comment on lines +1 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The docker-compose YAML uses service names cinema and db, but the project description and checklist expect services named app and db and that app always runs wait_for_db. Please rename service to app (or ensure README/test harness expects cinema) and ensure command calls python manage.py wait_for_db before migrations. Also ports map to 8001:8000 — the checklist expects 127.0.0.1:8000/api/ to work; change to "8000:8000" to expose on host port 8000.

dependencies = [
("cinema", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
Comment on lines +8 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The compose command should ensure the container runs the wait_for_db management command before migrate/runserver. The current command includes python manage.py wait_for_db but the repository lacks the wait_for_db management command implementation. Add cinema/management/commands/wait_for_db.py implementing polling logic that tries to connect to the DB until available.

]

operations = [
migrations.AlterField(
model_name="movie",
Comment on lines +10 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose defines db image as postgres:16-alpine3.17 which is fine, but the volumes entry uses my_db:$PGDATA — environment variable $PGDATA isn't defined here; better to map a named volume to the container path /var/lib/postgresql/data or use $PGDATA only if set in .env. This may prevent DB data persistence and cause container to fail.

name="actors",
field=models.ManyToManyField(
Comment on lines +9 to +19
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dockerfile creates /files/media and changes ownership to my_user, then switches to USER my_user. However later during container runtime some management commands (migrate) might need write access to other directories (e.g. collectstatic, migrations). Running migrations as non-root can fail if file permissions are not correct. Ensure that the app user has ownership of the project files or run management commands as root where required.

blank=True, related_name="movies", to="cinema.actor"
Comment on lines +1 to +20
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In settings.py DATABASES is still configured for SQLite. The task requires switching to PostgreSQL via environment variables. You must modify DATABASES to read host, port, name, user, password from environment (e.g. via os.environ) and use 'django.db.backends.postgresql'. This is a critical missing requirement.

),
),
migrations.AlterField(
model_name="movie",
name="genres",
field=models.ManyToManyField(
blank=True, related_name="movies", to="cinema.genre"
),
),
migrations.AlterField(
model_name="moviesession",
name="cinema_hall",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="movie_sessions",
to="cinema.cinemahall",
),
),
migrations.AlterField(
model_name="moviesession",
name="movie",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="movie_sessions",
to="cinema.movie",
),
),
migrations.AlterField(
model_name="order",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="orders",
to=settings.AUTH_USER_MODEL,
),
),
]
25 changes: 8 additions & 17 deletions cinema/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,10 @@ def __str__(self):
class MovieSession(models.Model):
show_time = models.DateTimeField()
movie = models.ForeignKey(
Movie,
on_delete=models.CASCADE,
related_name="movie_sessions"
Movie, on_delete=models.CASCADE, related_name="movie_sessions"
)
cinema_hall = models.ForeignKey(
CinemaHall,
on_delete=models.CASCADE,
related_name="movie_sessions"
CinemaHall, on_delete=models.CASCADE, related_name="movie_sessions"
)

class Meta:
Expand All @@ -106,15 +102,11 @@ class Meta:

class Ticket(models.Model):
movie_session = models.ForeignKey(
MovieSession,
on_delete=models.CASCADE,
related_name="tickets"
)
order = models.ForeignKey(
Order,
on_delete=models.CASCADE,
related_name="tickets"
MovieSession, on_delete=models.CASCADE, related_name="tickets"
)
order = models.ForeignKey(Order,
on_delete=models.CASCADE,
related_name="tickets")
row = models.IntegerField()
seat = models.IntegerField()

Expand Down Expand Up @@ -157,9 +149,8 @@ def save(
)

def __str__(self):
return (
f"{str(self.movie_session)} (row: {self.row}, seat: {self.seat})"
)
return f"{str(self.movie_session)}, "
f"(row: {self.row}, seat: {self.seat})"
Comment on lines 151 to +153
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Ticket.__str__ method has a syntax error. The f-string is split across lines 152-153, but only line 152's value is returned. Line 153 creates a separate unused f-string. Combine them into a single line: return f"{str(self.movie_session)}, (row: {self.row}, seat: {self.seat})"


class Meta:
unique_together = ("movie_session", "row", "seat")
Expand Down
11 changes: 4 additions & 7 deletions cinema/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ class Meta:

class MovieListSerializer(MovieSerializer):
genres = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="name"
)
many=True, read_only=True, slug_field="name")
actors = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="full_name"
)
Expand Down Expand Up @@ -90,8 +89,7 @@ class MovieSessionListSerializer(MovieSessionSerializer):
movie_title = serializers.CharField(source="movie.title", read_only=True)
movie_image = serializers.ImageField(source="movie.image", read_only=True)
cinema_hall_name = serializers.CharField(
source="cinema_hall.name", read_only=True
)
source="cinema_hall.name", read_only=True)
cinema_hall_capacity = serializers.IntegerField(
source="cinema_hall.capacity", read_only=True
)
Expand All @@ -117,7 +115,7 @@ def validate(self, attrs):
attrs["row"],
attrs["seat"],
attrs["movie_session"].cinema_hall,
ValidationError
ValidationError,
)
return data

Expand All @@ -140,8 +138,7 @@ class MovieSessionDetailSerializer(MovieSessionSerializer):
movie = MovieListSerializer(many=False, read_only=True)
cinema_hall = CinemaHallSerializer(many=False, read_only=True)
taken_places = TicketSeatsSerializer(
source="tickets", many=True, read_only=True
)
source="tickets", many=True, read_only=True)

class Meta:
model = MovieSession
Expand Down
14 changes: 5 additions & 9 deletions cinema/tests/test_movie_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ def sample_movie(**params):

def sample_movie_session(**params):
cinema_hall = CinemaHall.objects.create(
name="Blue", rows=20, seats_in_row=20
)
name="Blue", rows=20, seats_in_row=20)

defaults = {
"show_time": "2022-06-02 14:00:00",
Expand Down Expand Up @@ -94,8 +93,7 @@ def test_filter_movies_by_genres(self):
movie3 = sample_movie(title="Movie without genres")

res = self.client.get(
MOVIE_URL, {"genres": f"{genre1.id},{genre2.id}"}
)
MOVIE_URL, {"genres": f"{genre1.id},{genre2.id}"})

serializer1 = MovieListSerializer(movie1)
serializer2 = MovieListSerializer(movie2)
Expand All @@ -118,8 +116,7 @@ def test_filter_movies_by_actors(self):
movie3 = sample_movie(title="Movie without actors")

res = self.client.get(
MOVIE_URL, {"actors": f"{actor1.id},{actor2.id}"}
)
MOVIE_URL, {"actors": f"{actor1.id},{actor2.id}"})

serializer1 = MovieListSerializer(movie1)
serializer2 = MovieListSerializer(movie2)
Expand Down Expand Up @@ -147,9 +144,8 @@ def test_filter_movies_by_title(self):
def test_retrieve_movie_detail(self):
movie = sample_movie()
movie.genres.add(Genre.objects.create(name="Genre"))
movie.actors.add(
Actor.objects.create(first_name="Actor", last_name="Last")
)
movie.actors.add(Actor.objects.create(
first_name="Actor", last_name="Last"))

url = detail_url(movie.id)
res = self.client.get(url)
Expand Down
4 changes: 2 additions & 2 deletions cinema/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ def get_serializer_class(self):
"date",
type=OpenApiTypes.DATE,
description=(
"Filter by datetime of MovieSession "
"(ex. ?date=2022-10-23)"
"Filter by datetime"
"of MovieSession " "(ex. ?date=2022-10-23)"
),
),
]
Expand Down
19 changes: 16 additions & 3 deletions cinema_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
from datetime import timedelta
import os
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
Expand Down Expand Up @@ -84,10 +85,22 @@
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases

# DATABASES = {
# "default": {
# "ENGINE": "django.db.backends.sqlite3",
# "NAME": BASE_DIR / "db.sqlite3",
# }
# }


DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get("POSTGRES_DB"),
"USER": os.environ.get("POSTGRES_USER"),
"PASSWORD": os.environ.get("POSTGRES_PASSWORD"),
"HOST": os.environ.get("POSTGRES_HOST"),
"PORT": os.environ.get("POSTGRES_PORT"),
Comment on lines 96 to +103
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Settings: DATABASES is configured to use postgresql and reads connection parameters from environment variables — this satisfies the requirement to switch from SQLite to Postgres (good). Ensure your .env defines POSTGRES_DB/USER/PASSWORD/HOST/PORT and that docker-compose passes the env_file to both services.

}
}

Expand Down Expand Up @@ -134,7 +147,7 @@
STATIC_URL = "static/"

MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_ROOT = "/files/media"

# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
Comment on lines 151 to 153
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In cinema/models.py Ticket.str is split across multiple return expressions (two separate f-strings on adjacent lines with commas). That will not produce the intended single string. Combine into one formatted string, e.g. return f"{self.movie_session}, (row: {self.row}, seat: {self.seat})".

Expand Down
32 changes: 32 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
services:
cinema:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Service name is cinema. The task checklist expects services named app and db and specifically checks that app waits for db using wait_for_db. Rename cinema to app to match the checklist (or ensure automated checks expect cinema).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Service name is cinema. The checklist requires the application service be named app so commands in the task (docker-compose run app ...) work and the evaluator finds the service. Rename cinema:app:.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL - Checklist item #12: Service name must be app, not cinema. This is required for docker-compose run app commands to work correctly per checklist items #21 and #22.

build:
context: .
env_file:
- .env
ports:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL - Checklist item #13: Port mapping must be "8000:8000" so the API is accessible at 127://127.0.0.1:8000/api/ as specified in the task requirements. Change 8001 to 8000.

- "8001:8000"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ports mapping is "8001:8000", but the requirement states the DRF interface must be available at 127.0.0.1:8000. Change to "8000:8000" so the API is reachable at the expected host port.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Host port mapping is "8001:8000". The checklist explicitly requires the API to be available at 127.0.0.1:8000/api/, so change ports to "8000:8000" to expose container port 8000 on host port 8000.

command: >
sh -c "python manage.py wait_for_db &&
python manage.py makemigrations &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
Comment on lines +9 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The container command runs python manage.py makemigrations on startup. Generating migrations at container start is not recommended and is unnecessary for checklist validation. It can create unexpected migration files. Consider removing makemigrations and only run migrate after wait_for_db.

volumes:
- ./:/app
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Volume mapping for the app mounts the project directory ./:/app. This will override files copied into the image at build time and may cause permission issues (files owned by root overridden or mismatch). For production-like images consider avoiding bind mount or ensure file ownership is handled. For development it's acceptable but be aware.

- my_media:/files/media
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Media volume is mounted at /files/media while Django settings currently set MEDIA_ROOT to BASE_DIR / 'media'. This path mismatch will prevent uploaded images from persisting to the volume and cause tests to fail. Either change the mount point to /app/media or update Django MEDIA_ROOT to /files/media so they align.

Comment on lines +15 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Volume mapping - ./:/app mounts the project over the image filesystem; this is fine for development but can hide files baked into the image. Make sure this mount is intentional (for live code reload during dev) and that media persists via - my_media:/files/media (which matches settings.MEDIA_ROOT = '/files/media').

depends_on:
- db

db:
image: postgres:16-alpine3.17
restart: always
env_file:
- .env
ports:
- "5432:5432"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Service port mapping exposes Postgres on host ("5432:5432"). Exposing DB port is not required and can be omitted for improved security unless you need host access for debugging. Not required by checklist but worth considering.

Comment on lines +25 to +26
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Postgres service exposes 5432:5432. Exposing DB port to the host is not necessary for the task and can be avoided, but it's not a blocking issue. Also check the db service uses env variables from .env matching settings (POSTGRES_* names).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

db service uses env variables from .env

volumes:
- my_db:$PGDATA
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

DB service volume uses my_db:$PGDATA. Using $PGDATA here relies on an environment variable being defined (in .env). If PGDATA is not set in .env, this will expand to an empty string and the volume mapping will be invalid. Prefer - my_db:/var/lib/postgresql/data or explicitly set PGDATA in .env. Verify .env provides PGDATA if you intend to use it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

db volume uses - my_db:$PGDATA. Ensure the environment defines PGDATA or set a concrete container path (e.g. /var/lib/postgresql/data) for clarity. Current syntax relies on the environment variable being set which may be brittle in some environments.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

PGDATA is set in .env, and it is defined


volumes:
my_db:
my_media:
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ djangorestframework
djangorestframework-simplejwt
drf-spectacular
Pillow
psycopg==3.1.12
psycopg-binary==3.1.12
Loading