Веб-приложение для подсчёта очков в теннисном матче с сохранением результатов в базу данных. Учебный проект из роадмапа zhukovsd/python-backend-learning-course.
- Создание нового матча с двумя игроками
- Начисление очков по правилам тенниса: гейм, сет, дьюс, преимущество, тай-брейк при 6:6
- Матч играется до двух выигранных сетов
- Список сыгранных матчей с постраничной навигацией
- Поиск матчей по имени игрока
- Python 3.14
- WSGI без фреймворка, сервер Waitress
- Jinja2 — шаблоны
- SQLAlchemy 2.0 — ORM
- MySQL + PyMySQL
- Alembic — миграции схемы
- pytest — тесты
main.py точка входа, WSGI-приложение и таблица маршрутов
app/
controllers/ разбор HTTP-запроса и сборка ответа
services/ бизнес-логика: правила тенниса, работа с матчами
repositories/ запросы к базе данных
models.py описание таблиц
dtos.py объекты передачи данных для шаблонов
exceptions.py доменные исключения
responses.py сборка HTTP-ответов
database.py движок и сессии SQLAlchemy
template_renderer.py рендеринг Jinja2
static_handler.py раздача статики
templates/ HTML-шаблоны
static/ CSS, JS, изображения
alembic/ миграции
tests/ юнит-тесты подсчёта очков
Требуется установленный MySQL.
git clone <адрес репозитория>
cd tennis_scoreboard
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # Linux / macOS
pip install -r requirements.txtСоздать базу данных:
CREATE
DATABASE tennis_scoreboard_database CHARACTER SET utf8mb4;Скопировать .env.example в .env и указать свои параметры подключения:
cp .env.example .env| Переменная | Назначение | Пример |
|---|---|---|
DATABASE_URL |
Строка подключения к БД | mysql+pymysql://user:password@localhost:3306/tennis_scoreboard_database |
DEBUG |
Вывод SQL-запросов в консоль | True включает, любое другое значение выключает |
Применить миграции к базе:
alembic upgrade headAlembic берёт адрес базы из той же переменной DATABASE_URL, отдельно в alembic.ini его указывать не нужно.
python main.pyПриложение доступно по адресу http://127.0.0.1:8080
pytest| Адрес | Метод | Назначение |
|---|---|---|
/ |
GET | Главная |
/new-match |
GET | Форма создания матча |
/new-match |
POST | Создание матча, редирект на табло |
/match-score?uuid=<uuid> |
GET | Табло текущего матча |
/match-score?uuid=<uuid> |
POST | Начисление очка игроку |
/matches |
GET | Список сыгранных матчей, параметры page и filter_by_player_name |