From ad1c045784ee468c1055a503f98ddac623d94b15 Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 15:53:01 +0300 Subject: [PATCH 1/6] 'Solution' --- cinema_service/settings.py | 7 ++++++- requirements.txt | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 90dde772..e89880a8 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -83,11 +83,16 @@ # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases +import os DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", + "USER": os.getenv("DB_USER", "postgres"), + "PASSWORD": os.getenv("DB_PASS", "postgres"), + "HOST": os.getenv("DB_HOST", "localhost"), + "PORT": "5432", } } @@ -132,7 +137,7 @@ # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = "static/" - +STATIC_ROOT = "/vol/web/static" MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" diff --git a/requirements.txt b/requirements.txt index 2dc12c67..00c41709 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,9 @@ djangorestframework djangorestframework-simplejwt drf-spectacular Pillow + +black +djlint +crispy-bootstrap4 +pytest +pytest-django From 76a5247fa3c465beefcb04df67eb9f7b49d1f64f Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 15:53:16 +0300 Subject: [PATCH 2/6] 'Solution' --- .djlintrc | 6 ++++ Dockerfile | 30 +++++++++++++++++ cinema/management/commands/wait_for_db.py | 16 +++++++++ docker-compose.yml | 41 +++++++++++++++++++++++ pytest.ini | 5 +++ 5 files changed, 98 insertions(+) create mode 100644 .djlintrc create mode 100644 Dockerfile create mode 100644 cinema/management/commands/wait_for_db.py create mode 100644 docker-compose.yml create mode 100644 pytest.ini diff --git a/.djlintrc b/.djlintrc new file mode 100644 index 00000000..ac0322ee --- /dev/null +++ b/.djlintrc @@ -0,0 +1,6 @@ +{ + "indent": 2, + "max_line_length": 100, + "format_css": true, + "format_js": true +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..754969d8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.11-alpine +LABEL maintainer="student@mate.academy" + +ENV PYTHONUNBUFFERED 1 + +WORKDIR /app + +# Установка зависимостей системы +RUN apk add --update --no-cache \ + postgresql-client \ + jpeg-dev \ + libc-dev \ + linux-headers \ + postgresql-dev \ + zlib-dev + +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt + +COPY . . + +# Создание папок для статики и медиа +RUN mkdir -p /vol/web/media +RUN mkdir -p /vol/web/static + +# Безопасность: запуск от не-root пользователя +RUN adduser -D user +RUN chown -R user:user /vol/ +RUN chmod -R 755 /vol/web +USER user \ No newline at end of file diff --git a/cinema/management/commands/wait_for_db.py b/cinema/management/commands/wait_for_db.py new file mode 100644 index 00000000..06922c50 --- /dev/null +++ b/cinema/management/commands/wait_for_db.py @@ -0,0 +1,16 @@ +import time +from django.db import connections +from django.db.utils import OperationalError +from django.core.management.base import BaseCommand + +class Command(BaseCommand): + def handle(self, *args, **options): + self.stdout.write("Waiting for database...") + db_conn = None + while not db_conn: + try: + db_conn = connections["default"] + self.stdout.write(self.style.SUCCESS("Database available!")) + except OperationalError: + self.stdout.write("Database unavailable, waiting 1 second...") + time.sleep(1) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..d06722f7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +# @format + +version: '3.8' + +services: + db: + image: postgres:15-alpine + volumes: + - postgres_data:/var/lib/postgresql/data/ + environment: + - POSTGRES_DB=cinema + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + + app: + build: + context: . + ports: + - '8000:8000' + volumes: + - .:/app + - static_data:/vol/web/static + - media_data:/vol/web/media + environment: + - DB_HOST=db + - DB_NAME=cinema + - DB_USER=postgres + - DB_PASS=postgres + env_file: + - .env + command: > + sh -c "python manage.py wait_for_db && + python manage.py migrate && + python manage.py runserver 0.0.0.0:8000" + depends_on: + - db + +volumes: + postgres_data: + static_data: + media_data: diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..022df12f --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +DJANGO_SETTINGS_MODULE = cinema_service.settings +python_files = tests.py test_*.py *_tests.py +filterwarnings = + ignore::django.utils.deprecation.RemovedInDjango70Warning \ No newline at end of file From a390d0fc34124ef8ae3adc69aed9e577ac6ee014 Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 15:56:40 +0300 Subject: [PATCH 3/6] 'Solution' --- cinema/management/commands/wait_for_db.py | 1 + cinema_service/settings.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cinema/management/commands/wait_for_db.py b/cinema/management/commands/wait_for_db.py index 06922c50..58a83971 100644 --- a/cinema/management/commands/wait_for_db.py +++ b/cinema/management/commands/wait_for_db.py @@ -3,6 +3,7 @@ from django.db.utils import OperationalError from django.core.management.base import BaseCommand + class Command(BaseCommand): def handle(self, *args, **options): self.stdout.write("Waiting for database...") diff --git a/cinema_service/settings.py b/cinema_service/settings.py index e89880a8..e2e54ee6 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -11,6 +11,8 @@ """ from datetime import timedelta from pathlib import Path +import os + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -83,7 +85,7 @@ # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases -import os + DATABASES = { "default": { From 062a9b2bdf5583bca822e4019d4505ab15381d23 Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 16:12:00 +0300 Subject: [PATCH 4/6] 'Solution' --- cinema/management/commands/wait_for_db.py | 2 ++ cinema_service/settings.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cinema/management/commands/wait_for_db.py b/cinema/management/commands/wait_for_db.py index 58a83971..2e5f87b0 100644 --- a/cinema/management/commands/wait_for_db.py +++ b/cinema/management/commands/wait_for_db.py @@ -11,7 +11,9 @@ def handle(self, *args, **options): while not db_conn: try: db_conn = connections["default"] + db_conn.ensure_connection() self.stdout.write(self.style.SUCCESS("Database available!")) except OperationalError: self.stdout.write("Database unavailable, waiting 1 second...") + db_conn = None time.sleep(1) diff --git a/cinema_service/settings.py b/cinema_service/settings.py index e2e54ee6..044482f4 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -89,11 +89,11 @@ DATABASES = { "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", + "ENGINE": "django.db.backends.postgresql", + "NAME": os.getenv("DB_NAME", "cinema"), "USER": os.getenv("DB_USER", "postgres"), "PASSWORD": os.getenv("DB_PASS", "postgres"), - "HOST": os.getenv("DB_HOST", "localhost"), + "HOST": os.getenv("DB_HOST", "db"), # 'db' — имя сервиса в docker-compose "PORT": "5432", } } From ed91043582fd7ca8ac508b50c8cf4f2bcbefa0dd Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 16:12:13 +0300 Subject: [PATCH 5/6] 'Solution' --- .dockerignore | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..823a95a3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,43 @@ +dockerignore_content = """ +# Git +.git +.gitignore + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +.venv/ +pip-log.txt +pip-delete-this-directory.txt +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml +*.cover +*.log + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Docker +docker-compose.yml +Dockerfile +.dockerignore + +# Database & OS +*.sqlite3 +.DS_Store +db.sqlite3 +""" + +with open(".dockerignore", "w") as f: + f.write(dockerignore_content.strip()) \ No newline at end of file From c50d378bdba2319d880a93ed8c7cc27096d704bf Mon Sep 17 00:00:00 2001 From: martoff Date: Tue, 12 May 2026 16:14:06 +0300 Subject: [PATCH 6/6] 'Solution' --- cinema_service/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 044482f4..da8813fb 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -93,7 +93,8 @@ "NAME": os.getenv("DB_NAME", "cinema"), "USER": os.getenv("DB_USER", "postgres"), "PASSWORD": os.getenv("DB_PASS", "postgres"), - "HOST": os.getenv("DB_HOST", "db"), # 'db' — имя сервиса в docker-compose + # 'db' — имя сервиса в docker-compose + "HOST": os.getenv("DB_HOST", "db"), "PORT": "5432", } }