From 1c18ae96f72352e95284cf27b4c0f25f2e2b1d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=88=D0=BA=D0=B8=D0=BD=20=D0=A1=D0=B5=D1=80?= =?UTF-8?q?=D0=B3=D0=B5=D0=B9?= Date: Mon, 24 Nov 2025 13:57:31 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=20=D0=B4=D0=B5=D0=BF=D0=BB=D0=BE?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DEPLOYMENT_CHECKLIST.md | 249 --------------------- DEPLOYMENT_INSTRUCTIONS.md | 102 --------- DOCKER_README.md | 262 ---------------------- DOCKER_SETUP.md | 307 -------------------------- FILES_OVERVIEW.md | 240 -------------------- INSTALLATION_GUIDE.md | 167 -------------- OBJITEM_OPTIMIZATION_REPORT.md | 126 ----------- OPTIMIZATION_REPORT_SourceListView.md | 192 ---------------- QUERY_OPTIMIZATION_REPORT.md | 90 -------- QUICKSTART.md | 106 --------- QUICKSTART_ASYNC.md | 117 ---------- TASK_28_COMPLETION_SUMMARY.md | 135 ----------- dbapp/KUBSAT_FEATURE.md | 154 ------------- dbapp/mainapp/utils.py | 4 +- 14 files changed, 2 insertions(+), 2249 deletions(-) delete mode 100644 DEPLOYMENT_CHECKLIST.md delete mode 100644 DEPLOYMENT_INSTRUCTIONS.md delete mode 100644 DOCKER_README.md delete mode 100644 DOCKER_SETUP.md delete mode 100644 FILES_OVERVIEW.md delete mode 100644 INSTALLATION_GUIDE.md delete mode 100644 OBJITEM_OPTIMIZATION_REPORT.md delete mode 100644 OPTIMIZATION_REPORT_SourceListView.md delete mode 100644 QUERY_OPTIMIZATION_REPORT.md delete mode 100644 QUICKSTART.md delete mode 100644 QUICKSTART_ASYNC.md delete mode 100644 TASK_28_COMPLETION_SUMMARY.md delete mode 100644 dbapp/KUBSAT_FEATURE.md diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md deleted file mode 100644 index e2e8bd1..0000000 --- a/DEPLOYMENT_CHECKLIST.md +++ /dev/null @@ -1,249 +0,0 @@ -# Чеклист для деплоя в Production - -## Перед деплоем - -### 1. Безопасность - -- [ ] Сгенерирован новый `SECRET_KEY` - ```bash - python generate_secret_key.py - ``` - -- [ ] Изменены все пароли в `.env`: - - [ ] `DB_PASSWORD` - сильный пароль для PostgreSQL - - [ ] `POSTGRES_PASSWORD` - должен совпадать с `DB_PASSWORD` - -- [ ] Настроен `ALLOWED_HOSTS` в `.env`: - ``` - ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com - ``` - -- [ ] `DEBUG=False` в `.env` - -### 2. База данных - -- [ ] Проверены все миграции: - ```bash - docker-compose -f docker-compose.prod.yaml exec web python manage.py showmigrations - ``` - -- [ ] Настроен backup БД (cron job): - ```bash - 0 2 * * * cd /path/to/project && make backup - ``` - -### 3. Статические файлы - -- [ ] Проверена директория для статики: - ```bash - docker-compose -f docker-compose.prod.yaml exec web python manage.py collectstatic --noinput - ``` - -### 4. SSL/HTTPS (опционально, но рекомендуется) - -- [ ] Получены SSL сертификаты (Let's Encrypt, Certbot) -- [ ] Сертификаты размещены в `nginx/ssl/` -- [ ] Переименован `nginx/conf.d/ssl.conf.example` в `ssl.conf` -- [ ] Обновлен `server_name` в `ssl.conf` - -### 5. Nginx - -- [ ] Проверена конфигурация Nginx: - ```bash - docker-compose -f docker-compose.prod.yaml exec nginx nginx -t - ``` - -- [ ] Настроены правильные домены в `nginx/conf.d/default.conf` - -### 6. Docker - -- [ ] Проверен `.dockerignore` - исключены ненужные файлы -- [ ] Проверен `.gitignore` - не коммитятся секреты - -### 7. Переменные окружения - -Проверьте `.env` файл: - -```bash -# Django -DEBUG=False -ENVIRONMENT=production -DJANGO_SETTINGS_MODULE=dbapp.settings.production -SECRET_KEY=<ваш-длинный-секретный-ключ> - -# Database -DB_NAME=geodb -DB_USER=geralt -DB_PASSWORD=<сильный-пароль> -DB_HOST=db -DB_PORT=5432 - -# Allowed Hosts -ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com - -# PostgreSQL -POSTGRES_DB=geodb -POSTGRES_USER=geralt -POSTGRES_PASSWORD=<тот-же-сильный-пароль> - -# Gunicorn -GUNICORN_WORKERS=3 -GUNICORN_TIMEOUT=120 -``` - -## Деплой - -### 1. Клонирование репозитория - -```bash -git clone -cd -``` - -### 2. Настройка окружения - -```bash -cp .env.prod .env -nano .env # Отредактируйте все необходимые переменные -``` - -### 3. Запуск контейнеров - -```bash -docker-compose -f docker-compose.prod.yaml up -d --build -``` - -### 4. Проверка статуса - -```bash -docker-compose -f docker-compose.prod.yaml ps -docker-compose -f docker-compose.prod.yaml logs -f -``` - -### 5. Создание суперпользователя - -```bash -docker-compose -f docker-compose.prod.yaml exec web python manage.py createsuperuser -``` - -### 6. Проверка работоспособности - -- [ ] Открыть http://yourdomain.com -- [ ] Открыть http://yourdomain.com/admin -- [ ] Проверить статические файлы -- [ ] Проверить медиа файлы -- [ ] Проверить TileServer GL: http://yourdomain.com:8080 - -## После деплоя - -### 1. Мониторинг - -- [ ] Настроить мониторинг логов: - ```bash - docker-compose -f docker-compose.prod.yaml logs -f web - ``` - -- [ ] Проверить использование ресурсов: - ```bash - docker stats - ``` - -### 2. Backup - -- [ ] Настроить автоматический backup БД -- [ ] Проверить восстановление из backup -- [ ] Настроить backup медиа файлов - -### 3. Обновления - -- [ ] Документировать процесс обновления -- [ ] Тестировать обновления на dev окружении - -### 4. Безопасность - -- [ ] Настроить firewall (UFW, iptables) -- [ ] Ограничить доступ к портам: - - Открыть: 80, 443 - - Закрыть: 5432, 8000 (доступ только внутри Docker сети) - -- [ ] Настроить fail2ban (опционально) - -### 5. Производительность - -- [ ] Настроить кэширование (Redis, Memcached) -- [ ] Оптимизировать количество Gunicorn workers -- [ ] Настроить CDN для статики (опционально) - -## Troubleshooting - -### Проблема: Контейнеры не запускаются - -```bash -# Проверить логи -docker-compose -f docker-compose.prod.yaml logs - -# Проверить конфигурацию -docker-compose -f docker-compose.prod.yaml config -``` - -### Проблема: База данных недоступна - -```bash -# Проверить статус БД -docker-compose -f docker-compose.prod.yaml exec db pg_isready -U geralt - -# Проверить логи БД -docker-compose -f docker-compose.prod.yaml logs db -``` - -### Проблема: Статические файлы не загружаются - -```bash -# Пересобрать статику -docker-compose -f docker-compose.prod.yaml exec web python manage.py collectstatic --noinput - -# Проверить права доступа -docker-compose -f docker-compose.prod.yaml exec web ls -la /app/staticfiles -``` - -### Проблема: 502 Bad Gateway - -```bash -# Проверить, что Django запущен -docker-compose -f docker-compose.prod.yaml ps web - -# Проверить логи Gunicorn -docker-compose -f docker-compose.prod.yaml logs web - -# Проверить конфигурацию Nginx -docker-compose -f docker-compose.prod.yaml exec nginx nginx -t -``` - -## Полезные команды - -```bash -# Перезапуск сервисов -docker-compose -f docker-compose.prod.yaml restart web -docker-compose -f docker-compose.prod.yaml restart nginx - -# Обновление кода -git pull -docker-compose -f docker-compose.prod.yaml up -d --build - -# Backup БД -docker-compose -f docker-compose.prod.yaml exec db pg_dump -U geralt geodb > backup.sql - -# Восстановление БД -docker-compose -f docker-compose.prod.yaml exec -T db psql -U geralt geodb < backup.sql - -# Просмотр логов -docker-compose -f docker-compose.prod.yaml logs -f --tail=100 web - -# Очистка старых образов -docker system prune -a -``` - -## Контакты для поддержки - -- Документация: [DOCKER_README.md](DOCKER_README.md) -- Быстрый старт: [QUICKSTART.md](QUICKSTART.md) diff --git a/DEPLOYMENT_INSTRUCTIONS.md b/DEPLOYMENT_INSTRUCTIONS.md deleted file mode 100644 index 9202982..0000000 --- a/DEPLOYMENT_INSTRUCTIONS.md +++ /dev/null @@ -1,102 +0,0 @@ -# Инструкция по развертыванию изменений - -## Шаг 1: Применение миграций - -```bash -cd dbapp -python manage.py migrate -``` - -Это создаст таблицу `lyngsatapp_lyngsat` в базе данных. - -## Шаг 2: Запуск FlareSolver (если еще не запущен) - -FlareSolver необходим для обхода защиты Cloudflare на сайте Lyngsat. - -### Вариант 1: Docker -```bash -docker run -d -p 8191:8191 --name flaresolverr ghcr.io/flaresolverr/flaresolverr:latest -``` - -### Вариант 2: Docker Compose -Добавьте в `docker-compose.yaml`: -```yaml -services: - flaresolverr: - image: ghcr.io/flaresolverr/flaresolverr:latest - container_name: flaresolverr - ports: - - "8191:8191" - restart: unless-stopped -``` - -Затем запустите: -```bash -docker-compose up -d flaresolverr -``` - -## Шаг 3: Проверка работоспособности - -1. Запустите сервер разработки: -```bash -python manage.py runserver -``` - -2. Откройте браузер и перейдите на: -``` -http://localhost:8000/actions/ -``` - -3. Найдите карточку "Заполнение данных Lyngsat" и нажмите на кнопку - -4. Выберите один-два спутника для тестирования - -5. Выберите регионы (например, только Europe) - -6. Нажмите "Заполнить данные" и дождитесь завершения - -## Шаг 4: Проверка результатов - -1. Перейдите в админ-панель Django: -``` -http://localhost:8000/admin/ -``` - -2. Откройте раздел "Lyngsatapp" → "Источники LyngSat" - -3. Проверьте, что данные загружены корректно - -## Возможные проблемы и решения - -### Проблема: FlareSolver не отвечает -**Решение**: Проверьте, что FlareSolver запущен: -```bash -curl http://localhost:8191/v1 -``` - -### Проблема: Спутники не найдены в базе -**Решение**: Убедитесь, что спутники добавлены в базу данных. Используйте функцию "Добавление списка спутников" на странице действий. - -### Проблема: Долгое выполнение -**Решение**: Это нормально. Процесс может занять несколько минут на спутник. Начните с 1-2 спутников для тестирования. - -### Проблема: Ошибки при парсинге -**Решение**: Проверьте логи. Некоторые ошибки (например, некорректные частоты) не критичны и не прерывают процесс. - -## Откат изменений (если необходимо) - -Если нужно откатить изменения: - -```bash -# Откатить миграцию -python manage.py migrate lyngsatapp zero - -# Откатить изменения в коде -git checkout HEAD -- dbapp/ -``` - -## Дополнительная информация - -- Подробное руководство пользователя: `LYNGSAT_FILL_GUIDE.md` -- Сводка изменений: `CHANGES_SUMMARY.md` -- Документация по проекту: `README.md` diff --git a/DOCKER_README.md b/DOCKER_README.md deleted file mode 100644 index c3cde75..0000000 --- a/DOCKER_README.md +++ /dev/null @@ -1,262 +0,0 @@ -# Docker Setup для Django + PostGIS + TileServer GL - -## Структура проекта - -``` -. -├── dbapp/ # Django приложение -│ ├── Dockerfile # Универсальный Dockerfile -│ ├── entrypoint.sh # Скрипт запуска -│ └── ... -├── nginx/ # Конфигурация Nginx (только для prod) -│ └── conf.d/ -│ └── default.conf -├── tiles/ # Тайлы для TileServer GL -├── docker-compose.yaml # Development окружение -├── docker-compose.prod.yaml # Production окружение -├── .env.dev # Переменные для development -└── .env.prod # Переменные для production -``` - -## Быстрый старт - -### Development - -1. Скопируйте файл окружения: -```bash -cp .env.dev .env -``` - -2. Запустите контейнеры: -```bash -docker-compose up -d --build -``` - -3. Создайте суперпользователя: -```bash -docker-compose exec web python manage.py createsuperuser -``` - -4. Приложение доступно: - - Django: http://localhost:8000 - - TileServer GL: http://localhost:8080 - - PostgreSQL: localhost:5432 - -### Production - -1. Скопируйте и настройте файл окружения: -```bash -cp .env.prod .env -# Отредактируйте .env и измените SECRET_KEY, пароли и ALLOWED_HOSTS -``` - -2. Запустите контейнеры: -```bash -docker-compose -f docker-compose.prod.yaml up -d --build -``` - -3. Создайте суперпользователя: -```bash -docker-compose -f docker-compose.prod.yaml exec web python manage.py createsuperuser -``` - -4. Приложение доступно: - - Nginx: http://localhost (порт 80) - - Django (напрямую): http://localhost:8000 - - TileServer GL: http://localhost:8080 - - PostgreSQL: localhost:5432 - -## Основные команды - -### Development - -```bash -# Запуск -docker-compose up -d - -# Остановка -docker-compose down - -# Просмотр логов -docker-compose logs -f web - -# Выполнение команд Django -docker-compose exec web python manage.py migrate -docker-compose exec web python manage.py createsuperuser -docker-compose exec web python manage.py shell - -# Пересборка после изменений в Dockerfile -docker-compose up -d --build - -# Полная очистка (включая volumes) -docker-compose down -v -``` - -### Production - -```bash -# Запуск -docker-compose -f docker-compose.prod.yaml up -d - -# Остановка -docker-compose -f docker-compose.prod.yaml down - -# Просмотр логов -docker-compose -f docker-compose.prod.yaml logs -f web - -# Выполнение команд Django -docker-compose -f docker-compose.prod.yaml exec web python manage.py migrate -docker-compose -f docker-compose.prod.yaml exec web python manage.py createsuperuser - -# Пересборка -docker-compose -f docker-compose.prod.yaml up -d --build -``` - -## Различия между Dev и Prod - -### Development -- Django development server (runserver) -- DEBUG=True -- Код монтируется как volume (изменения применяются сразу) -- Без Nginx -- Простые пароли (для локальной разработки) - -### Production -- Gunicorn WSGI server -- DEBUG=False -- Код копируется в образ (не монтируется) -- Nginx как reverse proxy -- Сильные пароли и SECRET_KEY -- Сбор статики (collectstatic) -- Оптимизированные настройки безопасности - -## Переменные окружения - -### Основные переменные (.env) - -```bash -# Django -DEBUG=True/False -ENVIRONMENT=development/production -DJANGO_SETTINGS_MODULE=dbapp.settings.development/production -SECRET_KEY=your-secret-key - -# Database -DB_NAME=geodb -DB_USER=geralt -DB_PASSWORD=your-password -DB_HOST=db -DB_PORT=5432 - -# Allowed Hosts -ALLOWED_HOSTS=localhost,127.0.0.1,yourdomain.com - -# Gunicorn (только для production) -GUNICORN_WORKERS=3 -GUNICORN_TIMEOUT=120 -``` - -## Volumes - -### Development -- `postgres_data_dev` - данные PostgreSQL -- `static_volume_dev` - статические файлы -- `media_volume_dev` - медиа файлы -- `logs_volume_dev` - логи -- `./dbapp:/app` - код приложения (live reload) - -### Production -- `postgres_data_prod` - данные PostgreSQL -- `static_volume_prod` - статические файлы -- `media_volume_prod` - медиа файлы -- `logs_volume_prod` - логи - -## TileServer GL - -Для работы TileServer GL поместите ваши тайлы в директорию `./tiles/`. - -Пример структуры: -``` -tiles/ -├── config.json -└── your-tiles.mbtiles -``` - -## Backup и восстановление БД - -### Backup -```bash -# Development -docker-compose exec db pg_dump -U geralt geodb > backup.sql - -# Production -docker-compose -f docker-compose.prod.yaml exec db pg_dump -U geralt geodb > backup.sql -``` - -### Восстановление -```bash -# Development -docker-compose exec -T db psql -U geralt geodb < backup.sql - -# Production -docker-compose -f docker-compose.prod.yaml exec -T db psql -U geralt geodb < backup.sql -``` - -## Troubleshooting - -### Проблемы с миграциями -```bash -docker-compose exec web python manage.py migrate --fake-initial -``` - -### Проблемы с правами доступа -```bash -docker-compose exec -u root web chown -R app:app /app -``` - -### Очистка всех данных -```bash -docker-compose down -v -docker system prune -a -``` - -### Проверка логов -```bash -# Все сервисы -docker-compose logs -f - -# Конкретный сервис -docker-compose logs -f web -docker-compose logs -f db -``` - -## Безопасность для Production - -1. **Измените SECRET_KEY** - используйте длинный случайный ключ -2. **Измените пароли БД** - используйте сильные пароли -3. **Настройте ALLOWED_HOSTS** - укажите ваш домен -4. **Настройте SSL** - добавьте сертификаты в `nginx/ssl/` -5. **Ограничьте доступ к портам** - не открывайте порты БД наружу - -## Генерация SECRET_KEY - -```python -python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" -``` - -## Мониторинг - -### Проверка статуса контейнеров -```bash -docker-compose ps -``` - -### Использование ресурсов -```bash -docker stats -``` - -### Healthcheck -```bash -curl http://localhost:8000/admin/ -``` diff --git a/DOCKER_SETUP.md b/DOCKER_SETUP.md deleted file mode 100644 index f828048..0000000 --- a/DOCKER_SETUP.md +++ /dev/null @@ -1,307 +0,0 @@ -# Docker Setup - Полное руководство - -## 📋 Обзор - -Этот проект использует Docker для развертывания Django приложения с PostGIS и TileServer GL. - -**Основные компоненты:** -- Django 5.2 с PostGIS -- PostgreSQL 17 с расширением PostGIS 3.4 -- TileServer GL для работы с картографическими тайлами -- Nginx (только для production) -- Gunicorn WSGI сервер (production) - -## 🚀 Быстрый старт - -### Development -```bash -cp .env.dev .env -make dev-up -make createsuperuser -``` -Откройте http://localhost:8000 - -### Production -```bash -cp .env.prod .env -# Отредактируйте .env (SECRET_KEY, пароли, домены) -make prod-up -make prod-createsuperuser -``` -Откройте http://yourdomain.com - -## 📁 Структура файлов - -``` -. -├── dbapp/ # Django приложение -│ ├── Dockerfile # Универсальный Dockerfile -│ ├── entrypoint.sh # Скрипт инициализации -│ ├── .dockerignore # Исключения для Docker -│ └── ... -│ -├── nginx/ # Nginx конфигурация (prod) -│ ├── conf.d/ -│ │ ├── default.conf # HTTP конфигурация -│ │ └── ssl.conf.example # HTTPS конфигурация (пример) -│ └── ssl/ # SSL сертификаты -│ -├── tiles/ # Тайлы для TileServer GL -│ ├── README.md # Инструкция по настройке -│ ├── config.json.example # Пример конфигурации -│ └── .gitignore -│ -├── docker-compose.yaml # Development окружение -├── docker-compose.prod.yaml # Production окружение -│ -├── .env.dev # Переменные для dev -├── .env.prod # Переменные для prod (шаблон) -│ -├── Makefile # Удобные команды -├── generate_secret_key.py # Генератор SECRET_KEY -│ -└── Документация: - ├── QUICKSTART.md # Быстрый старт - ├── DOCKER_README.md # Подробная документация - ├── DEPLOYMENT_CHECKLIST.md # Чеклист для деплоя - └── DOCKER_SETUP.md # Этот файл -``` - -## 🔧 Конфигурация - -### Dockerfile - -**Один универсальный Dockerfile** для dev и prod: -- Multi-stage build для оптимизации размера -- Установка GDAL, PostGIS зависимостей -- Использование uv для управления зависимостями -- Non-root пользователь для безопасности -- Healthcheck для мониторинга - -### entrypoint.sh - -Скрипт автоматически: -- Ждет готовности PostgreSQL -- Выполняет миграции -- Собирает статику (только prod) -- Запускает runserver (dev) или Gunicorn (prod) - -Поведение определяется переменной `ENVIRONMENT`: -- `development` → Django development server -- `production` → Gunicorn WSGI server - -### docker-compose.yaml (Development) - -**Сервисы:** -- `db` - PostgreSQL с PostGIS -- `web` - Django приложение -- `tileserver` - TileServer GL - -**Особенности:** -- Код монтируется как volume (live reload) -- DEBUG=True -- Django development server -- Простые пароли для локальной разработки - -### docker-compose.prod.yaml (Production) - -**Сервисы:** -- `db` - PostgreSQL с PostGIS -- `web` - Django с Gunicorn -- `tileserver` - TileServer GL -- `nginx` - Reverse proxy - -**Особенности:** -- Код копируется в образ (не монтируется) -- DEBUG=False -- Gunicorn WSGI server -- Nginx для статики и проксирования -- Сильные пароли из .env -- Сбор статики (collectstatic) - -## 🔐 Безопасность - -### Для Production обязательно: - -1. **Сгенерируйте SECRET_KEY:** - ```bash - python generate_secret_key.py - ``` - -2. **Измените пароли БД** в `.env` - -3. **Настройте ALLOWED_HOSTS:** - ``` - ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com - ``` - -4. **Настройте SSL/HTTPS** (рекомендуется): - - Получите сертификаты (Let's Encrypt) - - Поместите в `nginx/ssl/` - - Используйте `nginx/conf.d/ssl.conf.example` - -5. **Ограничьте доступ к портам:** - - Открыть: 80, 443 - - Закрыть: 5432, 8000 - -## 📊 Мониторинг - -### Логи -```bash -# Development -make dev-logs - -# Production -make prod-logs - -# Конкретный сервис -docker-compose logs -f web -docker-compose logs -f db -``` - -### Статус -```bash -make status # Development -make prod-status # Production -docker stats # Использование ресурсов -``` - -### Healthcheck -```bash -curl http://localhost:8000/admin/ -``` - -## 💾 Backup и восстановление - -### Backup -```bash -make backup -# или -docker-compose exec db pg_dump -U geralt geodb > backup_$(date +%Y%m%d).sql -``` - -### Восстановление -```bash -docker-compose exec -T db psql -U geralt geodb < backup.sql -``` - -### Автоматический backup (cron) -```bash -# Добавьте в crontab -0 2 * * * cd /path/to/project && make backup -``` - -## 🔄 Обновление - -### Development -```bash -git pull -make dev-build -``` - -### Production -```bash -git pull -make prod-build -make prod-migrate -``` - -## 🗺️ TileServer GL - -Поместите `.mbtiles` файлы в директорию `tiles/`: - -```bash -tiles/ -├── world.mbtiles -└── satellite.mbtiles -``` - -Доступ: http://localhost:8080 - -Подробнее: [tiles/README.md](tiles/README.md) - -## 🛠️ Makefile команды - -### Development -```bash -make dev-up # Запустить -make dev-down # Остановить -make dev-build # Пересобрать -make dev-logs # Логи -make dev-restart # Перезапустить web -``` - -### Production -```bash -make prod-up # Запустить -make prod-down # Остановить -make prod-build # Пересобрать -make prod-logs # Логи -make prod-restart # Перезапустить web -``` - -### Django -```bash -make shell # Django shell -make migrate # Миграции -make makemigrations # Создать миграции -make createsuperuser # Создать суперпользователя -make collectstatic # Собрать статику -``` - -### Утилиты -```bash -make backup # Backup БД -make status # Статус контейнеров -make clean # Очистка (с volumes) -make clean-all # Полная очистка -``` - -## 📚 Дополнительная документация - -- **[QUICKSTART.md](QUICKSTART.md)** - Быстрый старт для нетерпеливых -- **[DOCKER_README.md](DOCKER_README.md)** - Подробная документация по Docker -- **[DEPLOYMENT_CHECKLIST.md](DEPLOYMENT_CHECKLIST.md)** - Чеклист для деплоя -- **[tiles/README.md](tiles/README.md)** - Настройка TileServer GL - -## ❓ Troubleshooting - -### Контейнеры не запускаются -```bash -docker-compose logs -docker-compose config -``` - -### База данных недоступна -```bash -docker-compose exec db pg_isready -U geralt -docker-compose logs db -``` - -### Статические файлы не загружаются -```bash -docker-compose exec web python manage.py collectstatic --noinput -docker-compose exec web ls -la /app/staticfiles -``` - -### 502 Bad Gateway -```bash -docker-compose ps web -docker-compose logs web -docker-compose exec nginx nginx -t -``` - -## 🎯 Следующие шаги - -1. ✅ Прочитайте [QUICKSTART.md](QUICKSTART.md) -2. ✅ Запустите development окружение -3. ✅ Изучите [DEPLOYMENT_CHECKLIST.md](DEPLOYMENT_CHECKLIST.md) перед деплоем -4. ✅ Настройте TileServer GL ([tiles/README.md](tiles/README.md)) -5. ✅ Настройте SSL для production - -## 📞 Поддержка - -При возникновении проблем: -1. Проверьте логи: `make dev-logs` или `make prod-logs` -2. Изучите документацию в этой директории -3. Проверьте [DOCKER_README.md](DOCKER_README.md) для подробностей diff --git a/FILES_OVERVIEW.md b/FILES_OVERVIEW.md deleted file mode 100644 index 4bbd12e..0000000 --- a/FILES_OVERVIEW.md +++ /dev/null @@ -1,240 +0,0 @@ -# Обзор созданных файлов Docker Setup - -## 🐳 Docker файлы - -### `dbapp/Dockerfile` -**Универсальный Dockerfile** для dev и prod окружений. -- Multi-stage build для оптимизации -- Установка GDAL, PostGIS, PostgreSQL клиента -- Использование uv для управления зависимостями -- Non-root пользователь для безопасности -- Healthcheck для мониторинга - -### `dbapp/entrypoint.sh` -**Скрипт инициализации контейнера.** -- Ожидание готовности PostgreSQL -- Автоматические миграции -- Сбор статики (только prod) -- Запуск runserver (dev) или Gunicorn (prod) - -### `dbapp/.dockerignore` -**Исключения для Docker build.** -- Исключает ненужные файлы из образа -- Уменьшает размер образа -- Ускоряет сборку - -## 🔧 Docker Compose файлы - -### `docker-compose.yaml` -**Development окружение.** -- PostgreSQL с PostGIS -- Django с development server -- TileServer GL -- Код монтируется как volume (live reload) -- DEBUG=True - -### `docker-compose.prod.yaml` -**Production окружение.** -- PostgreSQL с PostGIS -- Django с Gunicorn -- TileServer GL -- Nginx reverse proxy -- Код копируется в образ -- DEBUG=False -- Оптимизированные настройки - -## 🌐 Nginx конфигурация - -### `nginx/conf.d/default.conf` -**HTTP конфигурация для production.** -- Проксирование к Django -- Раздача статики и медиа -- Оптимизированные таймауты -- Кэширование статики - -### `nginx/conf.d/ssl.conf.example` -**HTTPS конфигурация (пример).** -- SSL/TLS настройки -- Редирект с HTTP на HTTPS -- Security headers -- Оптимизированные SSL параметры - -### `nginx/ssl/.gitkeep` -**Директория для SSL сертификатов.** -- Поместите сюда fullchain.pem и privkey.pem - -## 🗺️ TileServer GL - -### `tiles/README.md` -**Инструкция по настройке TileServer GL.** -- Как добавить тайлы -- Примеры конфигурации -- Использование в Django/Leaflet -- Где взять тайлы - -### `tiles/config.json.example` -**Пример конфигурации TileServer GL.** -- Настройки путей -- Форматы и качество -- Домены - -### `tiles/.gitignore` -**Исключения для git.** -- Игнорирует большие .mbtiles файлы -- Сохраняет примеры конфигурации - -## 🔐 Переменные окружения - -### `.env.dev` -**Переменные для development.** -- DEBUG=True -- Простые пароли для локальной разработки -- Настройки БД для dev - -### `.env.prod` -**Шаблон переменных для production.** -- DEBUG=False -- Требует изменения SECRET_KEY и паролей -- Настройки для production - -## 🛠️ Утилиты - -### `Makefile` -**Удобные команды для работы с Docker.** -- `make dev-up` - запуск dev -- `make prod-up` - запуск prod -- `make migrate` - миграции -- `make backup` - backup БД -- И многое другое - -### `generate_secret_key.py` -**Генератор Django SECRET_KEY.** -```bash -python generate_secret_key.py -``` - -## 📚 Документация - -### `QUICKSTART.md` -**Быстрый старт.** -- Минимальные команды для запуска -- Development и Production -- Основные команды - -### `DOCKER_README.md` -**Подробная документация.** -- Полное описание структуры -- Все команды с примерами -- Troubleshooting -- Backup и восстановление - -### `DOCKER_SETUP.md` -**Полное руководство.** -- Обзор всей системы -- Конфигурация -- Безопасность -- Мониторинг - -### `DEPLOYMENT_CHECKLIST.md` -**Чеклист для деплоя.** -- Пошаговая инструкция -- Проверка безопасности -- Настройка production -- Troubleshooting - -### `FILES_OVERVIEW.md` -**Этот файл.** -- Описание всех созданных файлов -- Назначение каждого файла - -## 📝 Обновленные файлы - -### `.gitignore` -**Обновлен для Docker.** -- Исключает .env файлы -- Исключает логи и backup -- Исключает временные файлы - -## 🎯 Как использовать - -### Для начала работы: -1. Прочитайте **QUICKSTART.md** -2. Выберите окружение (dev или prod) -3. Скопируйте соответствующий .env файл -4. Запустите с помощью Makefile - -### Для деплоя: -1. Прочитайте **DEPLOYMENT_CHECKLIST.md** -2. Следуйте чеклисту пошагово -3. Используйте **DOCKER_README.md** для справки - -### Для настройки TileServer: -1. Прочитайте **tiles/README.md** -2. Добавьте .mbtiles файлы -3. Настройте config.json (опционально) - -## 📊 Структура проекта - -``` -. -├── Docker конфигурация -│ ├── dbapp/Dockerfile -│ ├── dbapp/entrypoint.sh -│ ├── dbapp/.dockerignore -│ ├── docker-compose.yaml -│ └── docker-compose.prod.yaml -│ -├── Nginx -│ ├── nginx/conf.d/default.conf -│ ├── nginx/conf.d/ssl.conf.example -│ └── nginx/ssl/.gitkeep -│ -├── TileServer GL -│ ├── tiles/README.md -│ ├── tiles/config.json.example -│ └── tiles/.gitignore -│ -├── Переменные окружения -│ ├── .env.dev -│ └── .env.prod -│ -├── Утилиты -│ ├── Makefile -│ └── generate_secret_key.py -│ -└── Документация - ├── QUICKSTART.md - ├── DOCKER_README.md - ├── DOCKER_SETUP.md - ├── DEPLOYMENT_CHECKLIST.md - └── FILES_OVERVIEW.md -``` - -## ✅ Что было сделано - -1. ✅ Создан универсальный Dockerfile (один для dev и prod) -2. ✅ Настроен entrypoint.sh с автоматической инициализацией -3. ✅ Созданы docker-compose.yaml для dev и prod -4. ✅ Настроен Nginx для production -5. ✅ Добавлена поддержка TileServer GL -6. ✅ Созданы .env файлы для разных окружений -7. ✅ Добавлен Makefile с удобными командами -8. ✅ Написана подробная документация -9. ✅ Создан чеклист для деплоя -10. ✅ Добавлены утилиты (генератор SECRET_KEY) - -## 🚀 Следующие шаги - -1. Запустите development окружение -2. Протестируйте все функции -3. Подготовьте production окружение -4. Следуйте DEPLOYMENT_CHECKLIST.md -5. Настройте мониторинг и backup - -## 💡 Полезные ссылки - -- Django Documentation: https://docs.djangoproject.com/ -- Docker Documentation: https://docs.docker.com/ -- PostGIS Documentation: https://postgis.net/documentation/ -- TileServer GL: https://github.com/maptiler/tileserver-gl -- Nginx Documentation: https://nginx.org/en/docs/ diff --git a/INSTALLATION_GUIDE.md b/INSTALLATION_GUIDE.md deleted file mode 100644 index f326859..0000000 --- a/INSTALLATION_GUIDE.md +++ /dev/null @@ -1,167 +0,0 @@ -### Шаг 2: Применение миграций - -```bash -cd dbapp -python manage.py migrate -``` - -Это создаст: -- Таблицу `lyngsatapp_lyngsat` для данных Lyngsat -- Таблицы `django_celery_results_*` для результатов Celery - -### Шаг 3: Запуск сервисов - -```bash -# Запуск Redis и FlareSolver -docker-compose up -d redis flaresolverr - -# Проверка -redis-cli ping # Должно вернуть PONG -curl http://localhost:8191/v1 # Должно вернуть JSON -``` - -### Шаг 4: Запуск приложения - -**Терминал 1 - Django:** -```bash -cd dbapp -python manage.py runserver -``` - -**Терминал 2 - Celery Worker:** -```bash -cd dbapp -celery -A dbapp worker --loglevel=info -``` - -### Шаг 5: Тестирование - -1. Откройте `http://localhost:8000/actions/` -2. Нажмите "Заполнить данные Lyngsat" -3. Выберите спутники и регионы -4. Наблюдайте за прогрессом! - ---- - - -### Проверка Django -```bash -python dbapp/manage.py check -# Должно вывести: System check identified no issues (0 silenced). -``` - -### Проверка Celery (если установлен) -```bash -celery -A dbapp inspect ping -# Должно вывести: pong -``` - -### Проверка Redis (если установлен) -```bash -redis-cli ping -# Должно вывести: PONG -``` - -### Проверка FlareSolver -```bash -curl http://localhost:8191/v1 -# Должно вернуть JSON с информацией о сервисе -``` - ---- - - -### Проблема: FlareSolver не отвечает - -**Решение**: Запустите FlareSolver -```bash -docker-compose up -d flaresolverr -# или -docker run -d -p 8191:8191 ghcr.io/flaresolverr/flaresolverr:latest -``` - - -## Дополнительные инструменты - -### Flower - мониторинг Celery - -```bash -pip install flower -celery -A dbapp flower -# Откройте http://localhost:5555 -``` - -### Redis Commander - GUI для Redis - -```bash -docker run -d -p 8081:8081 --name redis-commander \ - --env REDIS_HOSTS=local:localhost:6379 \ - rediscommander/redis-commander -# Откройте http://localhost:8081 -``` - -### pgAdmin - GUI для PostgreSQL - -```bash -docker run -d -p 5050:80 --name pgadmin \ - -e PGADMIN_DEFAULT_EMAIL=admin@admin.com \ - -e PGADMIN_DEFAULT_PASSWORD=admin \ - dpage/pgadmin4 -# Откройте http://localhost:5050 -``` - ---- - - -### Остановка сервисов - -```bash -# Остановка Docker контейнеров -docker-compose down - -# Остановка Celery Worker -pkill -f "celery worker" -``` - -### Удаление данных - -```bash -# Удаление Docker volumes -docker-compose down -v - -# Удаление виртуального окружения -rm -rf dbapp/.venv - -# Удаление миграций (опционально) -find dbapp -path "*/migrations/*.py" -not -name "__init__.py" -delete -find dbapp -path "*/migrations/*.pyc" -delete -``` - -# Systemd service для запуска с хоста - -[Unit] -Description=Django Application -After=network.target - -[Service] -Type=notify -User=www-data -Group=www-data -WorkingDirectory=/path/to/your/app -Environment=PATH=/path/to/venv/bin -Environment=DATABASE_URL=postgresql://user:pass@localhost/geodb -ExecStart=/path/to/venv/bin/python manage.py runserver 0.0.0.0:8000 -ExecReload=/bin/kill -s HUP $MAINPID -TimeoutSec=300 -Restart=on-failure - -[Install] -WantedBy=multi-user.target - -## Поддержка - -1. Проверьте логи: - - Django: консоль где запущен runserver - - Celery: `dbapp/logs/celery_worker.log` - - Docker: `docker-compose logs` - diff --git a/OBJITEM_OPTIMIZATION_REPORT.md b/OBJITEM_OPTIMIZATION_REPORT.md deleted file mode 100644 index b78058e..0000000 --- a/OBJITEM_OPTIMIZATION_REPORT.md +++ /dev/null @@ -1,126 +0,0 @@ -# ObjItemListView Query Optimization Report - -## Дата: 2025-11-18 - -## Проблема - -При загрузке страницы списка ObjItems с большой пагинацией (500-1000 элементов) возникало **292+ дублирующихся SQL запросов** для получения mirrors (зеркал) через отношение ManyToMany: - -```sql -SELECT ••• FROM "mainapp_satellite" -INNER JOIN "mainapp_geo_mirrors" ON ("mainapp_satellite"."id" = "mainapp_geo_mirrors"."satellite_id") -WHERE "mainapp_geo_mirrors"."geo_id" = 4509 -ORDER BY 1 ASC -``` - -Это классическая проблема N+1 запросов, где для каждого ObjItem выполнялся отдельный запрос для получения связанных mirrors. - -## Решение - -### 1. Добавлен импорт Prefetch - -```python -from django.db.models import F, Prefetch -``` - -### 2. Создан оптимизированный Prefetch для mirrors - -```python -mirrors_prefetch = Prefetch( - 'geo_obj__mirrors', - queryset=Satellite.objects.only('id', 'name').order_by('id') -) -``` - -### 3. Применен Prefetch в обоих ветках queryset - -Для случая с выбранными спутниками: -```python -objects = ( - ObjItem.objects.select_related( - "geo_obj", - "source", - "updated_by__user", - "created_by__user", - "lyngsat_source", - "parameter_obj", - "parameter_obj__id_satellite", - "parameter_obj__polarization", - "parameter_obj__modulation", - "parameter_obj__standard", - "transponder", - "transponder__sat_id", - "transponder__polarization", - ) - .prefetch_related( - "parameter_obj__sigma_parameter", - "parameter_obj__sigma_parameter__polarization", - mirrors_prefetch, # ← Оптимизированный prefetch - ) - .filter(parameter_obj__id_satellite_id__in=selected_satellites) -) -``` - -### 4. Добавлены select_related для transponder - -Также добавлены оптимизации для transponder, которые ранее отсутствовали: -- `"transponder"` -- `"transponder__sat_id"` -- `"transponder__polarization"` - -## Результаты - -### До оптимизации -- **50 элементов**: ~295 запросов -- **100 элементов**: ~295 запросов -- **500 элементов**: ~295 запросов -- **1000 элементов**: ~295 запросов - -### После оптимизации -- **50 элементов**: **3 запроса** ✓ -- **100 элементов**: **3 запроса** ✓ -- **500 элементов**: **3 запроса** ✓ -- **1000 элементов**: **3 запроса** ✓ - -### Улучшение производительности - -| Метрика | До | После | Улучшение | -|---------|-----|-------|-----------| -| Запросов на 50 элементов | ~295 | 3 | **98.9%** ↓ | -| Запросов на 1000 элементов | ~295 | 3 | **98.9%** ↓ | -| Запросов на элемент | ~5.9 | 0.003 | **99.9%** ↓ | - -## Структура запросов после оптимизации - -1. **Основной запрос** - получение всех ObjItems с JOIN для всех select_related отношений -2. **Prefetch для sigma_parameter** - один запрос для всех sigma параметров -3. **Prefetch для mirrors** - один запрос для всех mirrors через geo_obj - -## Тестирование - -Созданы тестовые скрипты для проверки оптимизации: - -1. `test_objitem_query_optimization.py` - базовый тест -2. `test_objitem_detailed_queries.py` - детальный тест с доступом ко всем данным -3. `test_objitem_scale.py` - тест масштабируемости (50, 100, 500, 1000 элементов) - -Все тесты подтверждают, что количество запросов остается константным (3 запроса) независимо от размера страницы. - -## Соответствие требованиям - -Задача 29 из `.kiro/specs/django-refactoring/tasks.md`: - -- ✅ Добавлен select_related() для всех связанных моделей -- ✅ Добавлен prefetch_related() для mirrors (через Prefetch объект) -- ✅ Проверено количество запросов до и после оптимизации -- ✅ Требования 8.1, 8.2, 8.3, 8.4, 8.6 выполнены - -## Дополнительные улучшения - -1. Использован `Prefetch` объект вместо простой строки для более точного контроля -2. Добавлен `.only('id', 'name')` для mirrors, чтобы загружать только необходимые поля -3. Добавлен `.order_by('id')` для стабильного порядка результатов - -## Заключение - -Оптимизация успешно устранила проблему N+1 запросов для mirrors. Количество SQL запросов сокращено с ~295 до 3 (сокращение на **98.9%**), что значительно улучшает производительность страницы, особенно при больших размерах пагинации. diff --git a/OPTIMIZATION_REPORT_SourceListView.md b/OPTIMIZATION_REPORT_SourceListView.md deleted file mode 100644 index 9a4b324..0000000 --- a/OPTIMIZATION_REPORT_SourceListView.md +++ /dev/null @@ -1,192 +0,0 @@ -# SQL Query Optimization Report: SourceListView - -## Summary - -Successfully optimized SQL queries in `SourceListView` to eliminate N+1 query problems and improve performance. - -## Optimization Results - -### Query Count -- **Total queries**: 22 (constant regardless of page size) -- **Variation across page sizes**: 0 (perfectly stable) -- **Status**: ✅ EXCELLENT - -### Test Results - -| Page Size | Query Count | Status | -|-----------|-------------|--------| -| 10 items | 22 queries | ✅ Stable | -| 50 items | 22 queries | ✅ Stable | -| 100 items | 22 queries | ✅ Stable | - -**Key Achievement**: Query count remains constant at 22 regardless of the number of items displayed, proving there are no N+1 query problems. - -## Optimizations Applied - -### 1. select_related() for ForeignKey/OneToOne Relationships - -Added `select_related()` to fetch related objects in a single query using SQL JOINs: - -```python -sources = Source.objects.select_related( - 'info', # ForeignKey to ObjectInfo - 'created_by', # ForeignKey to CustomUser - 'created_by__user', # OneToOne to User (through CustomUser) - 'updated_by', # ForeignKey to CustomUser - 'updated_by__user', # OneToOne to User (through CustomUser) -) -``` - -**Impact**: Eliminates separate queries for each Source's info, created_by, and updated_by relationships. - -### 2. prefetch_related() for Reverse ForeignKey and ManyToMany - -Added comprehensive `prefetch_related()` to fetch related collections efficiently: - -```python -.prefetch_related( - # ObjItems and their nested relationships - 'source_objitems', - 'source_objitems__parameter_obj', - 'source_objitems__parameter_obj__id_satellite', - 'source_objitems__parameter_obj__polarization', - 'source_objitems__parameter_obj__modulation', - 'source_objitems__parameter_obj__standard', - 'source_objitems__geo_obj', - 'source_objitems__geo_obj__mirrors', # ManyToMany - 'source_objitems__lyngsat_source', - 'source_objitems__lyngsat_source__satellite', - 'source_objitems__transponder', - 'source_objitems__created_by', - 'source_objitems__created_by__user', - 'source_objitems__updated_by', - 'source_objitems__updated_by__user', - - # Marks and their relationships - 'marks', - 'marks__created_by', - 'marks__created_by__user' -) -``` - -**Impact**: Fetches all related ObjItems, Parameters, Geo objects, Marks, and their nested relationships in separate optimized queries instead of one query per item. - -### 3. annotate() for Efficient Counting - -Used `annotate()` with `Count()` to calculate objitem counts in the database: - -```python -.annotate( - objitem_count=Count('source_objitems', filter=objitem_filter_q, distinct=True) - if has_objitem_filter - else Count('source_objitems') -) -``` - -**Impact**: Counts are calculated in the database using GROUP BY instead of Python loops, and the count is available as an attribute on each Source object. - -## Query Breakdown - -The 22 queries consist of: - -1. **1 COUNT query**: For pagination (total count) -2. **1 Main SELECT**: Source objects with JOINs for select_related fields -3. **~20 Prefetch queries**: For all prefetch_related relationships - - ObjItems - - Parameters - - Satellites - - Polarizations - - Modulations - - Standards - - Geo objects - - Mirrors (ManyToMany) - - Transponders - - LyngsatSources - - CustomUsers - - Auth Users - - ObjectMarks - -## Performance Characteristics - -### Before Optimization (Estimated) -Without proper optimization, the query count would scale linearly with the number of items: -- 10 items: ~100+ queries (N+1 problem) -- 50 items: ~500+ queries -- 100 items: ~1000+ queries - -### After Optimization -- 10 items: 22 queries ✅ -- 50 items: 22 queries ✅ -- 100 items: 22 queries ✅ - -**Improvement**: ~95-98% reduction in query count for larger page sizes. - -## Compliance with Requirements - -### Requirement 8.1: Minimize SQL queries -✅ **ACHIEVED**: Query count reduced to 22 constant queries - -### Requirement 8.2: Use select_related() for ForeignKey/OneToOne -✅ **ACHIEVED**: Applied to info, created_by, updated_by relationships - -### Requirement 8.3: Use prefetch_related() for ManyToMany and reverse ForeignKey -✅ **ACHIEVED**: Applied to all reverse relationships and ManyToMany (mirrors) - -### Requirement 8.4: Use annotate() for aggregations -✅ **ACHIEVED**: Used for objitem_count calculation - -### Requirement 8.6: Reduce query count by at least 50% -✅ **EXCEEDED**: Achieved 95-98% reduction for typical page sizes - -## Testing Methodology - -Three test scripts were created to verify the optimization: - -1. **test_source_query_optimization.py**: Basic query count test -2. **test_source_query_detailed.py**: Detailed query analysis -3. **test_source_query_scale.py**: Scaling test with different page sizes - -All tests confirm: -- No N+1 query problems -- Stable query count across different page sizes -- Efficient use of Django ORM optimization techniques - -## Recommendations - -1. ✅ The optimization is complete and working correctly -2. ✅ Query count is well within acceptable limits (≤50) -3. ✅ No further optimization needed for SourceListView -4. 📝 Apply similar patterns to other list views (ObjItemListView, TransponderListView, etc.) - -## Bug Fix - -### Issue -Initial implementation had an incorrect prefetch path: -- ❌ `'source_objitems__lyngsat_source__satellite'` - -### Resolution -Fixed to use the correct field name from LyngSat model: -- ✅ `'source_objitems__lyngsat_source__id_satellite'` - -The LyngSat model uses `id_satellite` as the ForeignKey field name, not `satellite`. - -### Verification -Tested with 1000 items per page - no errors, 24 queries total. - -## Files Modified - -- `dbapp/mainapp/views/source.py`: Updated SourceListView.get() method with optimized queryset - -## Test Files Created - -- `test_source_query_optimization.py`: Basic optimization test -- `test_source_query_detailed.py`: Detailed query analysis -- `test_source_query_scale.py`: Scaling verification test -- `test_source_1000_items.py`: Large page size test (1000 items) -- `OPTIMIZATION_REPORT_SourceListView.md`: This report - ---- - -**Date**: 2025-11-18 -**Status**: ✅ COMPLETE (Bug Fixed) -**Task**: 28. Оптимизировать запросы в SourceListView diff --git a/QUERY_OPTIMIZATION_REPORT.md b/QUERY_OPTIMIZATION_REPORT.md deleted file mode 100644 index 78372ed..0000000 --- a/QUERY_OPTIMIZATION_REPORT.md +++ /dev/null @@ -1,90 +0,0 @@ -# Отчет об оптимизации запросов в ObjItemListView - -## Задача 29: Оптимизировать запросы в ObjItemListView - -### Выполненные изменения - -#### 1. Добавлены select_related() для всех связанных моделей -Добавлены следующие связи через `select_related()`: -- `transponder` -- `transponder__sat_id` -- `transponder__polarization` - -Эти связи уже были частично оптимизированы, но были добавлены недостающие. - -#### 2. Добавлены prefetch_related() для mirrors и marks -Использованы оптимизированные `Prefetch` объекты: - -```python -# Оптимизированный prefetch для mirrors через geo_obj -mirrors_prefetch = Prefetch( - 'geo_obj__mirrors', - queryset=Satellite.objects.only('id', 'name').order_by('id') -) - -# Оптимизированный prefetch для marks через source -marks_prefetch = Prefetch( - 'source__marks', - queryset=ObjectMark.objects.select_related('created_by__user').order_by('-timestamp') -) -``` - -#### 3. Исправлен доступ к mirrors -Изменен способ доступа к mirrors с `values_list()` на list comprehension: - -**Было:** -```python -mirrors_list = list(obj.geo_obj.mirrors.values_list('name', flat=True)) -``` - -**Стало:** -```python -mirrors_list = [mirror.name for mirror in obj.geo_obj.mirrors.all()] -``` - -Это критически важно, так как `values_list()` обходит prefetch_related и вызывает дополнительные запросы. - -### Результаты тестирования - -#### Тест 1: Сравнение с baseline (50 объектов) -- **До оптимизации:** 51 запрос -- **После оптимизации:** 4 запроса -- **Улучшение:** 92.2% (сокращение на 47 запросов) - -#### Тест 2: Масштабируемость -| Количество объектов | Запросов | -|---------------------|----------| -| 10 | 4 | -| 50 | 4 | -| 100 | 4 | -| 200 | 4 | - -**Результат:** ✓ PERFECT! Количество запросов остается постоянным независимо от количества объектов. - -### Структура запросов после оптимизации - -1. **Основной запрос:** SELECT для ObjItem с JOIN для всех select_related связей -2. **Prefetch mirrors:** SELECT для Satellite через geo_mirrors (ManyToMany) -3. **Prefetch source:** SELECT для Source (если не покрыто select_related) -4. **Prefetch marks:** SELECT для ObjectMark через source - -### Требования -Выполнены все требования задачи: -- ✓ 8.1 - Добавлен select_related() для всех связанных моделей -- ✓ 8.2 - Добавлен prefetch_related() для mirrors -- ✓ 8.3 - Добавлен prefetch_related() для marks -- ✓ 8.4 - Проверено количество запросов до и после оптимизации -- ✓ 8.6 - Оптимизация работает корректно - -### Файлы изменены -- `dbapp/mainapp/views/objitem.py` - добавлены оптимизации запросов - -### Тестовые файлы -- `test_objitem_final.py` - тест сравнения с baseline -- `test_objitem_scale.py` - тест масштабируемости -- `test_objitem_query_optimization.py` - базовый тест -- `test_objitem_detailed_queries.py` - детальный тест - -## Заключение - -Оптимизация успешно выполнена. Количество запросов к базе данных сокращено с ~51 до 4 запросов (улучшение на 92.2%), и это количество остается постоянным независимо от количества отображаемых объектов. Это значительно улучшит производительность страницы списка объектов, особенно при большом количестве записей. diff --git a/QUICKSTART.md b/QUICKSTART.md deleted file mode 100644 index ac873ab..0000000 --- a/QUICKSTART.md +++ /dev/null @@ -1,106 +0,0 @@ -# Быстрый старт с Docker - -## Development (разработка) - -```bash -# 1. Скопировать переменные окружения -cp .env.dev .env - -# 2. Запустить контейнеры -make dev-up -# или -docker-compose up -d --build - -# 3. Создать суперпользователя -make createsuperuser -# или -docker-compose exec web python manage.py createsuperuser - -# 4. Открыть в браузере -# Django: http://localhost:8000 -# Admin: http://localhost:8000/admin -# TileServer: http://localhost:8080 -``` - -## Production (продакшн) - -```bash -# 1. Скопировать и настроить переменные -cp .env.prod .env -nano .env # Измените SECRET_KEY, пароли, ALLOWED_HOSTS - -# 2. Запустить контейнеры -make prod-up -# или -docker-compose -f docker-compose.prod.yaml up -d --build - -# 3. Создать суперпользователя -make prod-createsuperuser -# или -docker-compose -f docker-compose.prod.yaml exec web python manage.py createsuperuser - -# 4. Открыть в браузере -# Nginx: http://localhost -# Django: http://localhost:8000 -# TileServer: http://localhost:8080 -``` - -## Полезные команды - -```bash -# Просмотр логов -make dev-logs # development -make prod-logs # production - -# Остановка -make dev-down # development -make prod-down # production - -# Перезапуск после изменений -make dev-build # development -make prod-build # production - -# Django shell -make shell # development -make prod-shell # production - -# Миграции -make migrate # development -make prod-migrate # production - -# Backup БД -make backup - -# Статус контейнеров -make status # development -make prod-status # production -``` - -## Структура проекта - -``` -. -├── dbapp/ # Django приложение -│ ├── Dockerfile # Универсальный Dockerfile -│ ├── entrypoint.sh # Скрипт запуска -│ ├── manage.py -│ └── ... -├── nginx/ # Nginx (только prod) -│ └── conf.d/ -│ └── default.conf -├── tiles/ # Тайлы для TileServer GL -│ ├── README.md -│ └── config.json.example -├── docker-compose.yaml # Development -├── docker-compose.prod.yaml # Production -├── .env.dev # Переменные dev -├── .env.prod # Переменные prod -├── Makefile # Команды для удобства -└── DOCKER_README.md # Подробная документация -``` - -## Что дальше? - -1. Прочитайте [DOCKER_README.md](DOCKER_README.md) для подробной информации -2. Настройте TileServer GL - см. [tiles/README.md](tiles/README.md) -3. Для production настройте SSL сертификаты в `nginx/ssl/` diff --git a/QUICKSTART_ASYNC.md b/QUICKSTART_ASYNC.md deleted file mode 100644 index 0dea2d2..0000000 --- a/QUICKSTART_ASYNC.md +++ /dev/null @@ -1,117 +0,0 @@ -# Быстрый старт: Асинхронное заполнение данных Lyngsat - -## Минимальная настройка (5 минут) - -### 1. Установите зависимости -```bash -pip install -r dbapp/requirements.txt -``` - -### 2. Примените миграции -```bash -cd dbapp -python manage.py migrate -``` - -### 3. Запустите необходимые сервисы - -**Терминал 1 - Redis и FlareSolver:** -```bash -docker-compose up -d redis flaresolverr -``` - -**Терминал 2 - Django:** -```bash -cd dbapp -python manage.py runserver -``` - -**Терминал 3 - Celery Worker:** -```bash -cd dbapp -celery -A dbapp worker --loglevel=info -``` - -### 4. Используйте систему - -1. Откройте браузер: `http://localhost:8000/actions/` -2. Нажмите "Заполнить данные Lyngsat" -3. Выберите 1-2 спутника для теста -4. Выберите регион (например, Europe) -5. Нажмите "Заполнить данные" -6. Наблюдайте за прогрессом в реальном времени! - -## Проверка работоспособности - -### Redis -```bash -redis-cli ping -# Должно вернуть: PONG -``` - -### FlareSolver -```bash -curl http://localhost:8191/v1 -# Должно вернуть JSON с информацией о сервисе -``` - -### Celery Worker -Проверьте вывод в терминале 3 - должны быть сообщения: -``` -[2024-01-15 10:30:00,000: INFO/MainProcess] Connected to redis://localhost:6379/0 -[2024-01-15 10:30:00,000: INFO/MainProcess] celery@hostname ready. -``` - -## Остановка сервисов - -```bash -# Остановить Docker контейнеры -docker-compose down - -# Остановить Django (Ctrl+C в терминале 2) - -# Остановить Celery Worker (Ctrl+C в терминале 3) -``` - -## Просмотр логов - -```bash -# Логи Celery Worker (если запущен с --logfile) -tail -f dbapp/logs/celery_worker.log - -# Логи Docker контейнеров -docker-compose logs -f redis -docker-compose logs -f flaresolverr -``` - -## Что дальше? - -- Прочитайте полную документацию: `ASYNC_LYNGSAT_GUIDE.md` -- Настройте production окружение -- Добавьте периодические задачи -- Настройте email уведомления - -## Решение проблем - -**Worker не запускается:** -```bash -# Проверьте Redis -redis-cli ping - -# Проверьте переменные окружения -echo $CELERY_BROKER_URL -``` - -**Задача не выполняется:** -```bash -# Проверьте FlareSolver -curl http://localhost:8191/v1 - -# Проверьте логи worker -tail -f dbapp/logs/celery_worker.log -``` - -**Прогресс не обновляется:** -- Откройте консоль браузера (F12) -- Проверьте Network tab на наличие ошибок -- Обновите страницу diff --git a/TASK_28_COMPLETION_SUMMARY.md b/TASK_28_COMPLETION_SUMMARY.md deleted file mode 100644 index e659cd6..0000000 --- a/TASK_28_COMPLETION_SUMMARY.md +++ /dev/null @@ -1,135 +0,0 @@ -# Task 28 Completion Summary: Optimize SourceListView Queries - -## ✅ Task Status: COMPLETED - -## Objective -Optimize SQL queries in SourceListView to eliminate N+1 query problems and improve performance by using Django ORM optimization techniques. - -## What Was Done - -### 1. Added select_related() for ForeignKey/OneToOne Relationships -Enhanced the queryset to fetch related objects using SQL JOINs: -- `info` (ForeignKey to ObjectInfo) -- `created_by` and `created_by__user` (ForeignKey to CustomUser → User) -- `updated_by` and `updated_by__user` (ForeignKey to CustomUser → User) - -### 2. Added prefetch_related() for Reverse ForeignKey and ManyToMany -Implemented comprehensive prefetching for all related collections: -- All `source_objitems` with nested relationships: - - `parameter_obj` and its related fields (satellite, polarization, modulation, standard) - - `geo_obj` and its mirrors (ManyToMany) - - `lyngsat_source` and its satellite - - `transponder` - - `created_by` and `updated_by` with their users -- All `marks` with their `created_by` relationships - -### 3. Used annotate() for Efficient Counting -Implemented database-level counting using `Count()` aggregation: -- Counts `objitem_count` in the database using GROUP BY -- Supports filtered counting when filters are applied -- Eliminates need for Python-level counting loops - -## Results - -### Query Performance -- **Total queries**: 22 (constant) -- **Scaling**: Perfect - query count remains at 22 regardless of page size -- **Status**: ✅ EXCELLENT - -### Test Results -| Page Size | Query Count | Variation | -|-----------|-------------|-----------| -| 10 items | 22 queries | 0 | -| 50 items | 22 queries | 0 | -| 100 items | 22 queries | 0 | - -### Performance Improvement -- **Before**: ~100-1000+ queries (N+1 problem, scales with items) -- **After**: 22 queries (constant, no scaling) -- **Improvement**: 95-98% reduction in query count - -## Requirements Compliance - -✅ **Requirement 8.1**: Minimize SQL queries to database -✅ **Requirement 8.2**: Use select_related() for ForeignKey/OneToOne -✅ **Requirement 8.3**: Use prefetch_related() for ManyToMany and reverse ForeignKey -✅ **Requirement 8.4**: Use annotate() instead of multiple queries in loops -✅ **Requirement 8.6**: Reduce query count by at least 50% (achieved 95-98%) - -## Files Modified - -### Production Code -- `dbapp/mainapp/views/source.py`: Updated SourceListView.get() method with optimized queryset - -### Test Files Created -- `test_source_query_optimization.py`: Basic query count verification -- `test_source_query_detailed.py`: Detailed query analysis with SQL output -- `test_source_query_scale.py`: Scaling test across different page sizes - -### Documentation -- `OPTIMIZATION_REPORT_SourceListView.md`: Comprehensive optimization report -- `TASK_28_COMPLETION_SUMMARY.md`: This summary document - -## Verification - -All optimizations have been verified through automated testing: - -1. ✅ Query count is stable at 22 regardless of page size -2. ✅ No N+1 query problems detected -3. ✅ All relationships properly optimized with select_related/prefetch_related -4. ✅ Counting uses database-level aggregation - -## Code Changes - -The main optimization in `dbapp/mainapp/views/source.py`: - -```python -sources = Source.objects.select_related( - 'info', - 'created_by', - 'created_by__user', - 'updated_by', - 'updated_by__user', -).prefetch_related( - 'source_objitems', - 'source_objitems__parameter_obj', - 'source_objitems__parameter_obj__id_satellite', - 'source_objitems__parameter_obj__polarization', - 'source_objitems__parameter_obj__modulation', - 'source_objitems__parameter_obj__standard', - 'source_objitems__geo_obj', - 'source_objitems__geo_obj__mirrors', - 'source_objitems__lyngsat_source', - 'source_objitems__lyngsat_source__satellite', - 'source_objitems__transponder', - 'source_objitems__created_by', - 'source_objitems__created_by__user', - 'source_objitems__updated_by', - 'source_objitems__updated_by__user', - 'marks', - 'marks__created_by', - 'marks__created_by__user' -).annotate( - objitem_count=Count('source_objitems', filter=objitem_filter_q, distinct=True) - if has_objitem_filter - else Count('source_objitems') -) -``` - -## Next Steps - -This optimization pattern should be applied to other list views: -- Task 29: ObjItemListView -- Task 30: TransponderListView -- Task 31: LyngsatListView -- Task 32: ObjectMarksListView - -## Conclusion - -Task 28 has been successfully completed with excellent results. The SourceListView now uses optimal Django ORM patterns to minimize database queries, resulting in a 95-98% reduction in query count and eliminating all N+1 query problems. - ---- - -**Completed**: 2025-11-18 -**Developer**: Kiro AI Assistant -**Status**: ✅ VERIFIED AND COMPLETE diff --git a/dbapp/KUBSAT_FEATURE.md b/dbapp/KUBSAT_FEATURE.md deleted file mode 100644 index 6a40c56..0000000 --- a/dbapp/KUBSAT_FEATURE.md +++ /dev/null @@ -1,154 +0,0 @@ -# Страница Кубсат - -## Описание -Страница "Кубсат" предназначена для фильтрации источников сигнала (Source) по различным критериям и экспорта результатов в Excel. - -## Доступ -Страница доступна по адресу: `/kubsat/` -Также добавлена в навигационное меню между "Наличие сигнала" и "3D карта". - -## Функциональность - -### Фильтры - -#### Реализованные фильтры: -1. **Спутники** (мультивыбор) - фильтрация по спутникам из связанных ObjItem -2. **Полоса спутника** (выбор) - выбор диапазона частот -3. **Поляризация** (мультивыбор) - фильтрация по поляризации сигнала -4. **Центральная частота** (диапазон) - фильтрация по частоте от/до в МГц -5. **Полоса** (диапазон) - фильтрация по полосе частот от/до в МГц -6. **Модуляция** (мультивыбор) - фильтрация по типу модуляции -7. **Тип объекта** (мультивыбор) - фильтрация по типу объекта (ObjectInfo) -8. **Количество привязанных ObjItem** (radio button): - - Все - - 1 - - 2 и более - -#### Фиктивные фильтры (заглушки): -9. **Принадлежность объекта** (мультивыбор) - пока не реализовано -10. **Планы на** (radio да/нет) - фиктивный фильтр -11. **Успех 1** (radio да/нет) - фиктивный фильтр -12. **Успех 2** (radio да/нет) - фиктивный фильтр -13. **Диапазон дат** (от/до) - фиктивный фильтр - -### Таблица результатов - -После применения фильтров отображается таблица на всю ширину страницы с колонками: -- ID Source - идентификатор источника (объединяет несколько точек) -- Тип объекта - тип источника -- Кол-во точек - количество точек источника (автоматически пересчитывается при удалении) -- Имя точки - название точки (ObjItem) -- Спутник (имя и NORAD ID) -- Частота (МГц) -- Полоса (МГц) -- Поляризация -- Модуляция -- Координаты ГЛ - координаты из geo_obj точки -- Дата ГЛ - дата геолокации точки -- Действия (кнопки удаления) - -**Важно**: -- Таблица показывает все точки (ObjItem) для каждого источника (Source) -- Точки одного источника группируются вместе -- Колонки ID Source, Тип объекта и Кол-во точек объединены для всех строк источника (rowspan) -- Количество точек автоматически пересчитывается при удалении строк -- Таблица имеет фиксированную высоту с прокруткой и sticky заголовок - -### Двухэтапная фильтрация - -Фильтрация происходит в два этапа: - -**Этап 1: Фильтрация по дате ГЛ** -- Если задан диапазон дат (от/до), отображаются только те точки, у которых дата ГЛ попадает в этот диапазон -- Точки без даты ГЛ исключаются, если фильтр по дате задан -- Если фильтр не задан, показываются все точки - -**Этап 2: Фильтрация по количеству точек** -- Применяется к уже отфильтрованным по дате точкам -- Варианты: - - "Все" - показываются источники с любым количеством точек - - "1" - только источники с ровно 1 точкой (после фильтрации по дате) - - "2 и более" - только источники с 2 и более точками (после фильтрации по дате) - -**Важно**: Фильтр по количеству точек учитывает только те точки, которые прошли фильтрацию по дате! - -### Управление данными в таблице - -**Кнопки удаления:** -- **Кнопка с иконкой корзины** (для каждой точки) - удаляет конкретную точку (ObjItem) из таблицы -- **Кнопка с иконкой заполненной корзины** (для первой точки источника) - удаляет все точки источника (Source) из таблицы - - - -**Важно**: Все удаления происходят только из таблицы, **БЕЗ удаления из базы данных**. Это позволяет пользователю исключить ненужные записи перед экспортом. - -### Экспорт в Excel - -Кнопка "Экспорт в Excel" создает файл со следующими колонками: -1. **Дата** - текущая дата (без времени) -2. **Широта, град** - рассчитывается как **инкрементальное среднее** из координат оставшихся в таблице точек -3. **Долгота, град** - рассчитывается как **инкрементальное среднее** из координат оставшихся в таблице точек -4. **Высота, м** - всегда 0 -5. **Местоположение** - из geo_obj.location первого ObjItem -6. **ИСЗ** - имя спутника и NORAD ID в скобках -7. **Прямой канал, МГц** - частота + перенос из транспондера -8. **Обратный канал, МГц** - частота источника -9. **Перенос** - из объекта Transponder -10. **Получено координат, раз** - количество точек (ObjItem), оставшихся в таблице для данного источника -11. **Период получения координат** - диапазон дат ГЛ в формате "5.11.2025-15.11.2025" (от самой ранней до самой поздней даты среди точек источника). Если все точки имеют одну дату, показывается только одна дата. -12. **Зеркала** - все имена зеркал через перенос строки (из оставшихся точек) -13. **СКО, км** - не заполняется -14. **Примечание** - не заполняется -15. **Оператор** - имя текущего пользователя - -**Важно**: -- Экспортируются только точки (ObjItem), оставшиеся в таблице после удалений -- Координаты рассчитываются по алгоритму инкрементального среднего из функции `calculate_mean_coords` (аналогично `fill_data_from_df`) -- Если пользователь удалил некоторые точки, координаты будут рассчитаны только по оставшимся - -Файл сохраняется с именем `kubsat_YYYYMMDD_HHMMSS.xlsx`. - -## Технические детали - -### Файлы -- **Форма**: `dbapp/mainapp/forms.py` - класс `KubsatFilterForm` -- **Представления**: `dbapp/mainapp/views/kubsat.py` - классы `KubsatView` и `KubsatExportView` -- **Шаблон**: `dbapp/mainapp/templates/mainapp/kubsat.html` -- **URL**: `/kubsat/` и `/kubsat/export/` - -### Зависимости -- openpyxl - для создания Excel файлов -- Django GIS - для работы с координатами - -### Оптимизация запросов -Используется `select_related` и `prefetch_related` для минимизации количества запросов к базе данных: -```python -queryset = Source.objects.select_related('info').prefetch_related( - 'source_objitems__parameter_obj__id_satellite', - 'source_objitems__parameter_obj__polarization', - 'source_objitems__parameter_obj__modulation', - 'source_objitems__transponder__sat_id' -) -``` - -## Использование - -1. Откройте страницу "Кубсат" из навигационного меню -2. Выберите нужные фильтры (спутники, поляризация, частота и т.д.) -3. Опционально укажите диапазон дат для фильтрации точек по дате ГЛ (Этап 1) -4. Опционально выберите количество точек (1 или 2+) - применяется к отфильтрованным по дате точкам (Этап 2) -5. Нажмите "Применить фильтры" -6. В таблице отобразятся точки (ObjItem) сгруппированные по источникам (Source) -7. При необходимости удалите отдельные точки или целые объекты кнопками в колонке "Действия" -8. Нажмите "Экспорт в Excel" для скачивания файла с оставшимися данными -9. Форма не сбрасывается после экспорта - можно продолжить работу - -## Примечания - -- Форма не сбрасывается после экспорта -- Удаление точек/объектов из таблицы не влияет на базу данных -- Экспортируются только оставшиеся в таблице точки -- Координаты в Excel рассчитываются как инкрементальное среднее из оставшихся точек -- Фильтр по дате скрывает неподходящие точки (не показывает их в таблице) -- Каждая строка таблицы = одна точка (ObjItem), строки группируются по источникам (Source) -- Количество точек в колонке "Кол-во точек" автоматически пересчитывается при удалении строк diff --git a/dbapp/mainapp/utils.py b/dbapp/mainapp/utils.py index b432172..0af86f8 100644 --- a/dbapp/mainapp/utils.py +++ b/dbapp/mainapp/utils.py @@ -125,9 +125,9 @@ def get_all_constants(): sats = [sat.name for sat in Satellite.objects.all()] standards = [sat.name for sat in Standard.objects.all()] pols = [sat.name for sat in Polarization.objects.all()] - mirrors = [sat.name for sat in Mirror.objects.all()] + # mirrors = [sat.name for sat in Mirror.objects.all()] modulations = [sat.name for sat in Modulation.objects.all()] - return sats, standards, pols, mirrors, modulations + return sats, standards, pols, modulations def find_mirror_satellites(mirror_names: list) -> list: