Учебный Django-проект для курсовой работы: сайт автосервиса и автокаталога с регистрацией пользователей, витриной машин и услуг, заявками на обслуживание/покупку и встроенным чатом поддержки.
README ниже задуман как одна точка входа в проект. По нему должно быть понятно:
- что делает сайт;
- что уже реализовано;
- как запустить проект локально;
- как выкатить изменения в прод;
- где хранятся данные, картинки и код;
- как управлять сайтом через GitHub, Render и Cloudinary;
- что делать, если сайт уснул, сломался деплой или пропали картинки;
- какие у проекта есть ограничения и риски.
Актуально для текущего развёртывания проекта:
- Сайт: https://autosite-zerodancing.onrender.com
- Админка: https://autosite-zerodancing.onrender.com/admin/
- GitHub-репозиторий: https://github.com/zerodancing/autosite
- Render Dashboard: https://dashboard.render.com/
- Cloudinary Console: https://console.cloudinary.com/
- Cloudinary Media Library: https://console.cloudinary.com/
Сайт совмещает несколько сценариев в одном интерфейсе:
- Витрина автомобилей.
- Каталог услуг автосервиса.
- Личный кабинет пользователя.
- Оформление заявок:
- запись на услугу;
- заявка по автомобилю.
- Встроенная поддержка с перепиской клиент <-> оператор.
- Админка для управления всем этим через Django Admin.
По сути это не просто лендинг, а полноценное CRUD-веб-приложение для демонстрации курсового проекта.
- Главная страница с современной витриной, быстрым поиском и подборками.
- Каталог машин:
- список;
- фильтрация по категории;
- поиск по марке, модели и описанию;
- карточка автомобиля;
- галерея изображений;
- характеристики автомобиля.
- Каталог услуг:
- список;
- фильтрация по категории;
- поиск;
- карточка услуги.
- Регистрация пользователя.
- Вход по
usernameилиemail. - Профиль пользователя.
- Переключение языка интерфейса.
- Переключение темы интерфейса.
- Оформление заявок:
- на услугу с желаемым временем;
- на автомобиль.
- Страница "Мои заказы".
- Страница отдельного заказа.
- Раздел поддержки:
- создание нового обращения;
- просмотр истории диалогов;
- переписка в чате;
- отправка изображений;
- отправка голосовых сообщений;
- запись голосового сообщения прямо в браузере;
- polling/AJAX-обновление сообщений с мягким backoff при ошибках.
- Django Admin на русском языке.
- Управление пользователями и ролями.
- Управление категориями услуг и самими услугами.
- Управление категориями машин и машинами.
- Загрузка и управление галереей изображений машин.
- Управление характеристиками машин и их значениями.
- Просмотр и обработка заказов.
- Просмотр диалогов поддержки и сообщений.
- Просмотр фото и прослушивание голосовых сообщений в админке.
В проекте уже есть автотесты на:
- logout через
POST; - вход по email;
- безопасное переключение языка;
- временную блокировку брутфорса на логине;
- загрузку галереи автомобилей;
- генерацию URL изображений;
- создание заказов;
- валидацию даты записи на услугу;
- валидацию комментариев;
- права доступа к чатам;
- отправку голосовых сообщений;
- создание обращения только с изображением без текста;
- мягкий rate limit на отправку сообщений в поддержку;
- CSRF для отправки сообщений;
- назначение оператора в чате.
На момент обновления этого README локально проходит 23 теста:
python manage.py testТакже в репозитории добавлен GitHub Actions workflow, который запускает manage.py check и manage.py test на push и pull request.
Текущий production устроен так:
- исходный код хранится на GitHub;
- приложение развёрнуто на Render как Python Web Service;
- регион текущего сервиса: Frankfurt;
- Django запускается через
gunicorn; DEBUG=False;- статика собирается через
collectstatic; - статика раздаётся через WhiteNoise;
- база данных хранится в Render Postgres;
- пользовательские изображения и медиа хранятся во внешнем storage, сейчас проект рассчитан на Cloudinary или S3-совместимое хранилище;
- Cloudinary storage в проекте настроен не только на изображения, но и на голосовые вложения;
- для текущего развёртывания медиа вынесены в Cloudinary;
- файловая система Render считается временной, поэтому хранить продовые медиа внутри контейнера нельзя.
Локально проект может работать проще:
- база:
db.sqlite3; - картинки: локальная папка
cars/; - запуск:
python manage.py runserverили черезstart.ps1/start.cmd. - часовой пояс проекта по умолчанию:
Europe/Moscowс возможностью переопределить черезDJANGO_TIME_ZONE.
Если работа идёт на исходном компьютере автора проекта, исходная папка с фотографиями была такой:
C:\Users\zerno\Desktop\Общая папка ВМ\Курсовая сайт Автосервис\autosite\cars
Если проект открыт в другой директории, ориентируйся уже на локальную папку cars/ внутри текущего checkout.
Ключевые модели проекта:
accounts.CustomUser:- пользователь;
- роль;
- ФИО;
- телефон.
catalog.ServiceCategoryиcatalog.Service:- категории услуг;
- услуги.
catalog.CarCategoryиcatalog.Car:- категории машин;
- карточки машин.
catalog.CarImage:- галерея изображений машины.
catalog.CarCharacteristicGroup,CarCharacteristic,CarCharacteristicValue:- характеристики автомобиля.
orders.Order:- заявки на услугу или автомобиль.
support.Conversationиsupport.Message:- поддержка и переписка.
Подробная схема есть в docs/ERD.md.
- Backend: Django 6
- WSGI: Gunicorn
- БД:
- локально
SQLite; - в проде
PostgreSQL
- локально
- Шаблоны: Django Templates
- UI: Tailwind CSS через CDN
- Медиа:
- локально
cars/; - в проде
Cloudinaryили S3-compatible storage
- локально
- Статика в проде: WhiteNoise
- Внешний хостинг: Render
autosite/
├─ accounts/ # аккаунты, авторизация, профиль, роли, bootstrap superuser
├─ autoservice/ # settings, urls, middleware, storage backends
├─ catalog/ # услуги, машины, характеристики, загрузка медиа, demo fixture
├─ orders/ # заказы и формы заявок
├─ support/ # чат поддержки и API polling
├─ templates/ # HTML-шаблоны
├─ docs/ # дополнительная документация
├─ scripts/ # вспомогательные скрипты
├─ cars/ # локальные исходные изображения, не для git/prod
├─ build.sh # build-скрипт для Render
├─ render.yaml # инфраструктурный конфиг Render
├─ requirements.txt # Python-зависимости
├─ start.ps1 # быстрый запуск на Windows PowerShell
├─ start.cmd # быстрый запуск на Windows CMD
└─ manage.py
PowerShell:
.\start.ps1или CMD:
start.cmdЧто делают эти скрипты:
- Переходят в папку проекта.
- Находят
venvили.venv. - При первом запуске ставят зависимости.
- Применяют миграции.
- Открывают браузер.
- Запускают
runserverна127.0.0.1:8000.
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txt
python manage.py migrate
python manage.py runserver 127.0.0.1:8000После запуска:
- Главная: http://127.0.0.1:8000/
- Админка: http://127.0.0.1:8000/admin/
- Поддержка: http://127.0.0.1:8000/support/
Классический способ:
python manage.py createsuperuserDev-хелпер для режима DEBUG=True:
/accounts/dev-admin-setup/
Этот endpoint создаёт/обновляет локального админа только в dev-режиме. В проде он отключён.
- Пользователь может войти по логину или по email.
- Logout работает только через
POST, что безопаснее обычнойGET-ссылки. - В админке интерфейс принудительно держится на русском языке.
Через /admin/ можно:
- создавать и редактировать пользователей;
- назначать роли;
- создавать категории услуг и сами услуги;
- создавать категории машин и карточки машин;
- загружать изображения машин;
- задавать характеристики автомобилей;
- смотреть и менять статусы заказов;
- читать обращения поддержки и отвечать в чатах.
- Открой
/admin/. - Создай или выбери
CarCategory. - Создай
Car. - Добавь изображения галереи.
- При необходимости добавь характеристики.
- Убедись, что
is_active=True.
- Открой
/admin/. - Создай или выбери
ServiceCategory. - Создай
Service. - Задай цену, длительность, описание.
- Добавь изображение.
- Убедись, что
is_active=True.
- Код: GitHub
- Веб-приложение: Render
- База данных: Render Postgres
- Изображения и медиа: Cloudinary
- Статика: внутри deploy-артефакта Render после
collectstatic
- Код: локальная папка проекта
- Локальная база:
db.sqlite3 - Локальные исходные изображения:
cars/
Обычный цикл работы такой:
git add .
git commit -m "Описание изменений"
git push origin mainПосле пуша в main Render делает новый деплой автоматически, если Auto-Deploy включён.
См. build.sh:
- ставит зависимости;
- запускает
collectstatic --clear; - применяет миграции;
- выполняет
ensure_bootstrap_superuser; - выполняет
ensure_demo_catalog; - выполняет
check --deploy.
См. render.yaml. Там зафиксированы:
DJANGO_SETTINGS_MODULE=autoservice.settings_productionDJANGO_DEBUG=0- build command:
bash ./build.sh - start command:
gunicorn autoservice.wsgi:application --log-file -
На free-плане Render сервис обычно не нужно вручную включать. Если он уснул, просто открой сайт по URL, и он проснётся сам.
Render -> Web Service -> Manual Deploy -> Restart service
Либо:
git push origin mainлибо в Render:
Manual Deploy -> Deploy latest commit
Render -> сервис -> Settings -> отключить Auto-Deploy
Render -> Manual Deploy -> Clear build cache & deploy
Render -> сервис -> Logs
Render -> сервис -> Environment
Render -> сервис -> Settings
Для текущей инфраструктуры это очень важно:
- web service засыпает примерно через
15 минутбез трафика; - при следующем открытии сам просыпается;
- пробуждение может занимать до минуты;
- у free web service нет persistent disk;
- у free web service нет shell;
- у free web service нет one-off jobs;
- на workspace даётся
750 instance hoursв месяц; - если часы кончатся, free web services будут приостановлены до следующего месяца.
Free Render Postgres живёт ограниченное время.
Для текущей базы, если она была создана 27 марта 2026, ориентиры такие:
- окончание срока free-базы: примерно
26 апреля 2026; - льготный период перед удалением: ещё около
14 дней; - возможное удаление без апгрейда: примерно после
10 мая 2026.
Если сайт нужен дольше тестов, базу надо перевести на платный тариф или перенести на другой сервер.
Потому что файловая система контейнера временная. Всё, что будет сохраняться внутрь самого сервиса, может потеряться после деплоя или рестарта.
Поэтому в проекте сделано правильное разделение:
- база отдельно;
- код отдельно;
- медиа отдельно.
- Локально картинки могут жить в
cars/. - В production медиа должны жить во внешнем хранилище.
- Проект умеет работать:
- с Cloudinary;
- с S3-compatible storage.
- Для чата поддержки во внешнее хранилище также уходят:
- изображения;
- голосовые сообщения.
Для текущего развёртывания основной и самый удобный вариант - Cloudinary.
Нужные переменные:
CLOUDINARY_CLOUD_NAMECLOUDINARY_API_KEYCLOUDINARY_API_SECRET
Cloudinary Console -> Assets / Media Library
Проверить:
- что в Render заданы Cloudinary-переменные;
- что в Cloudinary картинка реально появилась;
- что
MEDIA_URLи storage backend корректно поднялись в проде; - что в логах нет
ImproperlyConfigured.
Если есть локальная папка cars/, а проект уже настроен на production storage:
python manage.py sync_media_to_storage --settings autoservice.settings_productionЕсли нужно перезалить поверх:
python manage.py sync_media_to_storage --settings autoservice.settings_production --overwriteВажно: команда специально проверяет, что default_storage не указывает на локальный MEDIA_ROOT.
В проекте есть fixture:
catalog/fixtures/catalog_demo_seed.json
Он содержит демо-каталог машин и может автоматически загрузиться в пустую базу.
DJANGO_LOAD_DEMO_FIXTURE=0Если поставить 1, build-скрипт сможет подгрузить демо-каталог в пустую базу.
python manage.py ensure_demo_catalog --forceЕсли ты уже убедился, что каталог машин загружен и всё на месте, лучше держать:
DJANGO_LOAD_DEMO_FIXTURE=0Если в текущем Render-окружении это временно стоит в 1, после проверки лучше вернуть обратно в 0.
В проекте есть команда:
python manage.py ensure_bootstrap_superuserОна срабатывает только если явно включить:
DJANGO_BOOTSTRAP_SUPERUSER=1
DJANGO_BOOTSTRAP_SUPERUSER_USERNAME=...
DJANGO_BOOTSTRAP_SUPERUSER_PASSWORD=...
DJANGO_BOOTSTRAP_SUPERUSER_EMAIL=...Если эта связка не нужна, оставляй:
DJANGO_BOOTSTRAP_SUPERUSER=0Актуальный шаблон см. в .env.production.example.
Минимально важные production-переменные:
DJANGO_SETTINGS_MODULE=autoservice.settings_production
DJANGO_DEBUG=0
DJANGO_TIME_ZONE=Europe/Moscow
DJANGO_SECRET_KEY=replace-with-a-long-random-secret-key
DJANGO_SITE_URL=https://example.com
DJANGO_ALLOWED_HOSTS=example.com,www.example.com,example.onrender.com
DJANGO_CSRF_TRUSTED_ORIGINS=https://example.com,https://www.example.com,https://example.onrender.com
DATABASE_URL=postgresql://user:password@host:5432/database
DJANGO_DB_CONN_MAX_AGE=600
DJANGO_BOOTSTRAP_SUPERUSER=0
DJANGO_LOAD_DEMO_FIXTURE=0
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=- В production обязателен
DJANGO_SECRET_KEY. - В production обязателен корректный
DATABASE_URLили Postgres-настройки. - Для production обязателен внешний storage для медиа.
- Если Cloudinary не настроен, должен быть настроен S3-compatible storage.
- Без корректных
ALLOWED_HOSTSиCSRF_TRUSTED_ORIGINSпроект не должен стартовать.
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver 127.0.0.1:8000
python manage.py check
python manage.py testpython manage.py check --deploypython manage.py ensure_demo_catalog --forcepython manage.py sync_media_to_storage --settings autoservice.settings_productionСкорее всего, Render-экземпляр уснул. Для free-плана это нормально.
Проверь:
- пуш точно ушёл в
main; - в Render включён
Auto-Deploy; - деплой не упал в логах;
- при необходимости запусти
Deploy latest commit.
Порядок проверки:
- Logs в Render;
- env-переменные;
ALLOWED_HOSTS/CSRF_TRUSTED_ORIGINS;DATABASE_URL;- Cloudinary credentials;
- при странном кэше
Clear build cache & deploy.
Проверь, не сохранились ли они в локальную файловую систему вместо Cloudinary. В production так делать нельзя.
Скрипты используют файл .deps_ready как маркер, что зависимости уже ставились. Если ты менял requirements.txt, проще вручную выполнить:
pip install -r requirements.txtили удалить .deps_ready и запустить скрипт снова.
Кратко:
- CSRF включён;
- XSS снижается за счёт autoescape и безопасной вставки текста;
- закрытые страницы защищены через
login_required; - logout переведён на
POST; - есть базовые security headers;
- есть лёгкий cache-based rate limit на логин, создание обращений, отправку сообщений и polling чата;
- есть мягкая временная блокировка брутфорса на логине;
- в чате есть простейший антиспам-лимит на частую отправку подряд;
- загрузки в чат ограничены по типу и размеру файлов;
- редирект при переключении языка проверяется безопасно.
Подробнее см. docs/SECURITY.md.
Если проект будет жить дольше демонстрации или пойдёт в публичный доступ, стоит обязательно:
- Поставить
DJANGO_LOAD_DEMO_FIXTURE=0. - Поменять
CLOUDINARY_API_SECRET. - Поменять
DATABASE_URLили пароль базы. - Поменять
DJANGO_SECRET_KEY. - Проверить
ALLOWED_HOSTSиCSRF_TRUSTED_ORIGINS. - Подумать о переезде с free Postgres.
Это хороший учебный проект, но важно честно понимать его границы:
- Нет реальных платежей и платёжных интеграций.
- Чат построен на polling, а не на WebSocket-реальном времени.
- Free Render засыпает и ограничен по ресурсам.
- Free Postgres на Render временный и может быть удалён по сроку.
- Тесты уже есть и теперь гоняются в CI, но покрытие всё ещё частичное.
- Лёгкие rate limits реализованы на локальном кэше Django, а не на внешнем edge/WAF, поэтому это базовая защита, а не полноценная анти-DDoS-инфраструктура.
- Прод целиком зависит от корректных внешних env-переменных и внешних сервисов.
- Медиа в проде нельзя хранить в контейнере Render, только во внешнем storage.
Если будет время развивать проект после курсовой, хороший порядок такой:
- Расширить тесты на каталог, авторизацию и админские сценарии.
- Добавить нормальные роли и разграничение прав операторов.
- Перевести чат на WebSocket/Channels.
- Сделать резервное копирование базы и медиа.
- Убрать зависимость от free Postgres.
- render.yaml - конфиг развёртывания Render
- build.sh - build/deploy pipeline
- .env.production.example - пример production-env
- .github/workflows/django-tests.yml - CI-проверка
checkиtest - docs/DEPLOY_RENDER.md - заметки по деплою
- docs/SECURITY.md - безопасность
- docs/ERD.md - схема данных
- Render free plan: https://render.com/docs/free
- Render deploys: https://render.com/docs/deploys
- Render + Django: https://render.com/docs/deploy-django
- Cloudinary Django integration: https://cloudinary.com/documentation/django_integration
Если нужен совсем короткий сценарий на каждый день:
- Меняешь код локально.
- Проверяешь сайт локально.
- Запускаешь
python manage.py test. - Делаешь
git add,git commit,git push. - Проверяешь деплой в Render.
- Если нужно, смотришь логи.
- Если сайт уснул, просто открываешь URL.
- Если сломался кэш сборки, делаешь
Clear build cache & deploy. - Контент редактируешь через
/admin/. - Картинки смотришь в Cloudinary Media Library.
Если README перестаёт совпадать с реальностью, обновляй в первую очередь:
- ссылки;
- env-переменные;
- способ хранения медиа;
- build/start-команды;
- ограничения хостинга;
- порядок деплоя.