15 KiB
AGENTS.md — Окнардия: Оконный Агрегатор
Версия: 0.2.0 | Язык: Python 3.12+ + Django 6.0+ | БД: MariaDB/MySQL
Этот документ обеспечивает AI-агентов (Copilot, Claude, Cursor и т.д.) контекстом для эффективной работы с проектом.
Архитектура и назначение
Окнардия — это агрегатор для сравнения цен на установку оконных конструкций в зданиях типового (серийного) строительства в России. Пользователи вводят адрес дома → система распознаёт серию строения → выдаёт типовые размеры оконных проемов → показывает предложения от поставщиков на установку (замену) окон.
Архитектура двухуровневая:
- Основной проект:
oknardia/(Django settings, URL routing, models, templates) - Приложение логики:
web/(views, вспомогательные функции, кеширование схем окон)
Критические компоненты и модели данных
Основные модели (oknardia/models.py)
Иерархия зданий:
Seria_Info— серия типового строения (P-44, 5-этажка и т.п.), поддерживает self-referential FK для древовидной структурыBuilding_Info— конкретный адрес с ссылкой на серию; содержит ~30 полей метаданных (площадь, износ, материалы)Apartment_Type— типовой план квартиры в серии; содержит связь M2M сWin_MountDimMountDim2Apartment— через-таблица между проёмами и квартирами
Каталог и цены:
PVCprofiles— PVC-профили (окна), содержат рейтинг (0…+5) и tech-specsGlazing— стеклопакеты с изоляционными параметрами и рейтингомSetKit— готовый "набор" (профиль + стеклопакет + фурнитура + монтаж), связывает компоненты и хранит бизнес-условияPriceOffer— финальная цена для конкретного проёма и набора от конкретного пользователя
Дополнительные сущности:
OurUser— собственная система пользователей (расширение Django User)MerchantBrand/MerchantOffice— организационная иерархия поставщиковBlogPosts— универсальная таблица для блога и каталога (одна таблица, флагиbCatalog,bPublished)- Несколько LOG-таблиц:
LogMeasure,LogDemand,LogVisitPriceReport
Именование полей (обязательное соглашение):
s*= String/Chari*= Integerf*= Float/Decimalb*= Booleand*= DateTime/Datek*= Foreign Key (связь)p*= Path/Media- Например:
sSetName— название набора,fSetRating— рейтинг набора
Кеширование и специфика
-
Картинки схем окон генерируются автоматически в:
public/static/img/_flap.cfg— большие картинки схем открыванияpublic/static/img/_miniflap.cfg— миниатюры для таблиц- Важно: не удалять просто так, они переиспользуются; если схема архивируется, картинка остаётся без явного удаления
-
Pre-render HTML-шаблоны для серий в
oknardia/templates/seria_info/prepared/- Создаются при первом обращении к странице серии
- Требуют ручной очистки при изменении цен/спецификаций или настройки cronjob на удаление
-
Кольцевой буфер логирования (настройка
MAX_LEN_RING_LOG_BUFFER=250в settings)
Workflow и точки входа
Основной сценарий пользователя:
- Главная (
/) →views.main_init()— отслеживание кук посещений - Автокомплит адреса (
/autocomplete_addr) →autocomplete_addr.autocomplete_addr()— подсказки при вводе - Поиск по адресу (
/get_address) →views.get_address()— распознание серии здания - Ценовая выдача (
/{build_id}/{apart_id}/*) →prices.report_price()— основной отчёт с фильтрацией и пагинацией по фреймам
Каталоги и отчёты:
catalog.py— каталог профилей, производителей, серий (с методомcatalog_seria_info())report1.py— сравнение наборов (compare_offers()) с расчётом рейтинговых компонентreport2.py— рейтинги и ранжирование (фильтрация по звёздочкам и весам)diagrams.py— статистика и аналитика
Система пользователей:
user_manager.py— регистрация, логин/logout, восстановление пароля, верификация email- Использует собственные таблицы
OurUser+ стандартный DjangoUser
Специфические технологии и паттерны
Конфигурация через settings.py:
- Двойной хост (DEV и PROD) по
socket.gethostname()— разные БД, media-пути, сценарии отладки - Настройки ранжирования через веса (более 20 констант типа
RANK_STEP_*,RARING_*) - Google Captcha и Yandex Maps API ключи из
my_secret.py
Импорт конфиденциальных данных:
from oknardia.my_secret import * # в settings.py и models.py
⚠️ Важно: my_secret.py содержит пароли БД, SECRET_KEY и должен быть в .gitignore
Использование JSON в моделях:
- Поле
sProfileDescription(Profiles),sGlazingDescription,sSetDescription— JSON или HTML в TextField - Нет явной валидации структуры JSON при сохранении
Система рейтинга и ранжирования:
- Каждый компонент (профиль, стеклопакет, набор) имеет рейтинг
- Веса рейтинга задают важность каждого атрибута (теплопередача, звукоизоляция и т.п.)
report1.show_rating_components()раскрывает формулу расчёта рейтинга
Интернационализация:
LANGUAGE_CODE = 'ru-RU',TIME_ZONE = 'Europe/Moscow'USE_I18N = True,FIRST_DAY_OF_WEEK = 1(понедельник)- Все названия моделей и help_text на русском языке
Конвенции кодирования
Из .github/copilot-instructions.md:
✅ Обязательные правила:
- Язык: отвечай на русском, комментарии кода на русском
- Стиль: PEP 8 для Python, используй современные возможности (Python 3.12+, Django 6.0+)
- Управление зависимостями:
poetry(вместо pip/requirements.txt) - Переменные окружения: секреты в
.env, не в коде - Git коммиты:
add: <описание>— новая функция/файлfix: <описание>— багmod: <описание>— переработка кодаminor: <описание>— форматирование, опечатки, мелкие комменты
- Удаление старого кода: помечать меткой
# Удалить:, не стирать просто - Тон: неформальный, профессиональный, образность допускается (как с коллегой)
⚠️ Исключения:
- Не удаляй старый код без явного указания
- Всегда уточняй перед
git commit/git push - Если модель требует миграций, опиши шаги для
python manage.py makemigrations/migrate
Типичные рабочие циклы
Добавление нового фильтра в ценовую выдачу:
- Добавить поле в модель (например,
SetKit) → создать миграцию - Обновить фильтрацию в
prices.report_price()→ использовать Q-объекты - Обновить template для выбора фильтра (
templates/price/*.html) - Проверить влияние на рейтинг в
report1.pyесли нужно
Обновление рейтинга и ранжирования:
- Модифицировать вес в settings.py (RANK_STEP_, RARING_)
- Пересчитать рейтинг в моделях через функцию
save()или создать management-command - Проверить результаты в
report2.ratings()иreport2.profiles_rating()
Кеширование и производительность:
- Картинки схем кешируются автоматически; при добавлении новой схемы нужно явно вызвать функцию генерации
- Pre-render HTML нужно чистить при обновлении ценовых данных (см. управление файлами в
seria_info/prepared/) - БД индексирована на часто используемых полях (
db_index=True)
Разработка на macOS:
- При установке
mysqlclientможет потребоватьсяbrew install mariadb-connector-c - Подробнее см. README.md, раздел "Некоторые заметки относительно разработки"
Структура папок
oknardia/
├── manage.py
├── oknardia/
│ ├── models.py # ВСЕ модели (1900+ строк)
│ ├── settings.py # конфиг, импорт my_secret.py
│ ├── urls.py # маршруты (113 строк)
│ ├── admin.py
│ ├── views.py # главная, контакты, тариф
│ └── my_secret.py # CONFIDENTIAL: пароли, ключи
├── web/
│ ├── views.py # основная логика
│ ├── add_func.py # утилиты (геокод, расстояния)
│ ├── prices.py # отчёты ценовой выдачи
│ ├── report1.py # сравнение наборов
│ ├── report2.py # рейтинги и ранжирование
│ ├── catalog.py # каталоги
│ ├── diagrams.py # статистика
│ ├── blog.py # список и посты блога
│ ├── autocomplete_addr.py # автокомплит адресов
│ ├── user_manager.py # логин, регистрация
│ └── service.py # служебные функции (sitemap, очистка)
├── templates/ # Django шаблоны (Jinja2-like)
│ ├── base.html
│ ├── index.html # главная
│ ├── seria_info/prepared/ # пре-рендер кеш
│ ├── price/
│ ├── catalog/
│ └── ...
└── public/
├── static/
│ ├── img/_flap.cfg/ # схемы окон (большие)
│ ├── img/_miniflap.cfg/ # схемы окон (мини)
│ ├── css/
│ ├── js/
│ └── ...
└── media/ # загружаемые файлы
Отладка и команды
# Разработка
python manage.py runserver # локальный сервер
python manage.py makemigrations # подготовить миграцию
python manage.py migrate # применить миграцию
# Администрирование
python manage.py shell # интерпретатор с контекстом Django
python manage.py createsuperuser # создать админа
python manage.py collectstatic # собрать статику для продакшена
# Служебные (см. service.py)
# Находятся в urls.py: /service/make_sitemaps, /service/make_rating
Типичные ошибки и подводные камни
- Забывчивость миграций: при добавлении полей в модель сразу создавай миграцию
- Нарушение именования полей: новые поля должны начинаться с префикса (s, i, f, b, d, k, p)
- Незакешированные картинки: если добавляешь новую схему открывания, вызови функцию генерации явно
- Неочищенные pre-render шаблоны: могут вызвать устаревание данных на страницах серий
- Foreign Key ON_DELETE: используется в основном
DO_NOTHINGиSET_NULL, будь осторожен при удалении - Двойной хост: убедись, что используешь правильные переменные из
my_secret.pyдля текущей машины - Индексирование БД: большинство полей для поиска уже имеют
db_index=True, но проверь при добавлении фильтров
Реферальные ссылки (для более глубокого изучения)
- Django 6.0+ docs: https://docs.djangoproject.com/en/stable/
- MariaDB/MySQL: Конфиг БД в settings.py, ENGINE = "django.db.backends.mysql"
- Система рейтинга: см. functions в report1.py и constants в settings.py (RANK_, RARING_)
- Фронтенд: Bootstrap 3.3.7 (в static/bootstrap-3.3.7-dist.zip), jQuery, Yandex Maps API
Автор инструкций: проанализировано 16.04.2026
Версия документа: 1.0
Последнее обновление: инструкции в .github/copilot-instructions.md