7 KiB
7 KiB
FitnessCenter — эксплуатационная документация
Назначение
Одностраничный лендинг и личный кабинет фитнес‑клуба с регистрацией, входом и покупкой абонементов. Рендеринг на сервере (Django), без JSON API.
Стек
- Python 3.13, Django 5.1.4
- Bootstrap 5.3 (CDN), шрифт Manrope, кастомный тёмный UI
static/css/main.css - БД по умолчанию: SQLite (
db.sqlite3); совместимо с Postgres - Контейнеризация: Dockerfile (python:3.13-slim) +
docker-compose.yml(порт 1337→8000)
Архитектура и файлы
gymclub/— настройки Django, URL‑маршрутизация верхнего уровня.club/— доменная логика: модели, формы, views, urls, context processor с адресами клубов.templates/— серверные шаблоны:base.html,home.html,register.html,login.html,dashboard.html.static/— стили и логотип, подключаются через{% static %}; собранные файлы кладутся вstaticfiles/.entrypoint.sh— миграции +collectstatic(ошибки игнорируются) и запускrunserverна 0.0.0.0:8000.www/— архивная статическая версия лендинга (не используется приложением).
Данные и бизнес‑логика
MembershipPlan: имя, описание, длительность в днях, цена. Начальные тарифы создаются миграцией0002_default_plans.Profile: OneToOne к пользователю, хранит телефон.Subscription: ссылка на пользователя и план, даты начала/окончания;is_activeпроверяетend_date≥ сегодня.- Хелпер
Subscription.create_for_plan(user, plan)рассчитывает дату окончания от текущей даты и создаёт запись — используйте его вместо ручного сохранения. - Проверка телефона (RegistrationForm): нормализует «8» в «+7», требует 11 цифр формата +7XXXXXXXXXX.
- Парольные валидаторы стандартные, но проверка «простых паролей» отключена (CommonPasswordValidator не подключён).
Маршруты (HTML API)
Все пути объявлены в club/urls.py, подключены в gymclub/urls.py.
GET /— витрина с планами, адресами клубов.GET /register/,POST /register/— регистрация пользователя, автологин, создание Profile.GET /login/,POST /login/— аутентификация через Django AuthenticationForm.GET /logout/— logout + redirect домой (view используетlogout, форма не нужна).GET /dashboard/(требует авторизации) — активный абонемент, история, покупка новых.POST /subscribe/<int:plan_id>/— покупка плана черезSubscription.create_for_plan.admin/— стандартная админка для планов, подписок и профилей. Все формы защищены CSRF; сообщения пользователю выводятся через Django messages.
UI и контент
- Тёмная тема с акцентным цветом
--accentвstatic/css/main.css; поменяйте переменные в корне файла для ребрендинга. - Список клубов задаётся константой
CLUBSвclub/context_processors.pyи доступен в шаблонах какclubs. - Главная страница содержит секции «Абонементы», «Тренеры», «Клубы», «О нас» и форму заявки в футере (пока без обработки).
Переменные окружения
Файл примера .env.example:
DJANGO_DEBUG(True/False)DJANGO_ALLOWED_HOSTS(список через запятую,*по умолчанию)DJANGO_SECRET_KEY(смените в проде) Дополнительно вsettings.py: языкru-ru, часовой поясEurope/Moscow.
Запуск
В Docker
cp .env.example .env
docker compose build
docker compose up
# Откройте http://localhost:1337
Контейнер монтирует текущую директорию, так что правки видны без пересборки.
Локально (без Docker)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # при необходимости отредактируйте
python manage.py migrate
python manage.py runserver
Админка и данные
- Создайте суперпользователя:
python manage.py createsuperuser. - Начальные планы создаются миграцией; новые можно добавить через /admin/ или фикстуры.
Переключение на Postgres (кратко)
- Добавьте сервис в
docker-compose.ymlили поднимите внешнюю БД. - В
gymclub/settings.pyзадайтеENGINE = 'django.db.backends.postgresql'и параметрыNAME/USER/PASSWORD/HOST/PORT(лучше через переменные окружения). - Выполните миграции заново (
python manage.py migrate).
Хитрости и рекомендации
- Используйте
Subscription.create_for_plan— он правильно считаетend_dateот текущего дня. - Телефон хранится в нормализованном формате
+7XXXXXXXXXX; это можно использовать для SMS‑интеграций. - Планы отсортированы по цене (
ordering = ['price']), поэтому вывод на главной будет от дешёвого к дорогому. entrypoint.shне падает, еслиcollectstaticбез настроек S3; удобнее для локалки, но в проде задайтеSTATIC_ROOTи уберите|| trueпри необходимости.- Блок футера «Позвоните мне» пока статический — если нужна отправка заявки, повесьте action на форму и добавьте view.
Полезные пути
- Основной код:
club/views.py,club/forms.py,club/models.py - Стили:
static/css/main.css - Шаблоны:
templates/ - Контейнеризация:
Dockerfile,docker-compose.yml,entrypoint.sh