1
0
Fork 0
mirror of https://github.com/EDeev/deev.space.git synced 2026-10-07 20:49:59 +03:00

README на русском и английском, документация, скриншоты, лицензия MIT

- README.md и README.en.md: что это, статус, скриншоты, быстрый старт в Docker,
  установка без Docker, переменные окружения, схема, развёртывание, разработка;
- docs/architecture.md (модели, оценки без регистрации, антинакрутка, безопасность)
  и docs/deploy.md (Docker и устройство боевого сервера) вместо описания моделей в README;
- файл LICENSE (MIT), который раньше был заявлен только в README.
This commit is contained in:
Деев Егор Викторович 2026-10-02 12:23:09 +00:00
parent a04709d3df
commit a696d996b9
10 changed files with 315 additions and 348 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Egor Deev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

128
README.en.md Normal file
View file

@ -0,0 +1,128 @@
# deev.space
[Русский](README.md) · **English**
[![CI](https://github.com/EDeev/deev.space/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/deev.space/actions/workflows/ci.yml)
[![Docker](https://github.com/EDeev/deev.space/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/deev.space/actions/workflows/docker.yml)
[![Release](https://img.shields.io/github/v/release/EDeev/deev.space)](https://github.com/EDeev/deev.space/releases)
[![License](https://img.shields.io/github/license/EDeev/deev.space)](LICENSE)
Personal portfolio website of a Python developer: projects, blog, experience and tech stack, article
ratings without sign-up. Source code of [deev.space](https://deev.space).
**Status:** personal project, actively developed · live at [deev.space](https://deev.space)
![deev.space home page](docs/screenshots/main.png)
**Stack:** Python 3.12 · Django 4.2 · SQLite · bleach · Yandex SmartCaptcha · gunicorn + nginx · Docker
## Features
- Home page with a profile card, tech stack by category and a "by the numbers" block
- Blog: categories, galleries, attachments, links with automatic previews, threaded comments
- Likes and dislikes without sign-up, based on a signed cookie and limited per IP
- Unique article views with bot filtering
- Projects, achievements, experience and education, all editable in the admin
- Contact form with captcha and a Telegram notification to the owner
- `sitemap.xml`, readable URLs, custom 404 and 500 pages
## Quick start
```bash
git clone https://github.com/EDeev/deev.space.git && cd deev.space
cp .env.example .env # set DJANGO_SECRET_KEY
docker compose up -d
docker compose exec web python manage.py createsuperuser
```
The site runs at `http://localhost:8000`, the admin at `/admin/`. Prebuilt image:
`docker pull ghcr.io/edeev/deev.space` or `docker pull dcr.deev.su/edeev/deev.space`.
## Installing without Docker
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # for development: DJANGO_DEBUG=True
python manage.py migrate
python manage.py populate_demo # demo content, optional
python manage.py createsuperuser
python manage.py runserver
```
## Configuration
All settings are environment variables (full list in [`.env.example`](.env.example)):
| Variable | Purpose |
|---|---|
| `DJANGO_SECRET_KEY` | Django secret key, required with `DJANGO_DEBUG=False` |
| `DJANGO_DEBUG` | debug mode, `False` by default |
| `DJANGO_ALLOWED_HOSTS`, `DJANGO_CSRF_TRUSTED_ORIGINS` | comma-separated site domains |
| `DJANGO_DB_PATH`, `DJANGO_MEDIA_ROOT` | location of the SQLite database and uploaded files |
| `SMARTCAPTCHA_CLIENT_KEY`, `SMARTCAPTCHA_SERVER_KEY` | Yandex SmartCaptcha for the contact form |
| `EMAIL_*`, `CONTACT_EMAIL` | sending contact form messages by email |
| `ALERTBOT_TOKEN`, `ALERTBOT_CHAT_ID` | Telegram notification to the owner about a new message |
| `SOCIAL_AUTOPOST`, `TELEGRAM_*`, `VK_*` | auto-posting new articles, off by default |
> [!IMPORTANT]
> With `DJANGO_DEBUG=False` the site enables HSTS and redirects to HTTPS. To run without TLS (locally or
> behind a proxy that terminates HTTPS), set `DJANGO_SECURE_SSL_REDIRECT=False`.
## Screenshots
| About | Projects |
|---|---|
| ![About](docs/screenshots/about.png) | ![Projects](docs/screenshots/projects.png) |
| **Blog** | **Mobile** |
| ![Blog](docs/screenshots/blog.png) | ![Mobile](docs/screenshots/mobile.png) |
## How it works
```mermaid
flowchart LR
B[Browser] --> N[nginx<br/>TLS, static, media]
N --> G[gunicorn]
G --> D[Django: main]
D --> S[(SQLite)]
D -.-> T[Telegram / AlertBot]
D -.-> C[Yandex SmartCaptcha]
```
A single `main` app: models for content, ratings and site settings, class-based views, a JSON API for
ratings and comments, and an anonymous visitor middleware. Details (in Russian):
- [docs/architecture.md](docs/architecture.md) — models, ratings without sign-up, anti-abuse, security
- [docs/deploy.md](docs/deploy.md) — running in Docker and how the production server is set up
## Deployment
[deev.space](https://deev.space) runs on a VPS: gunicorn under a dedicated user behind nginx with a
Let's Encrypt certificate; nginx serves static files and uploads. Prometheus monitors availability and
certificate expiry. GitHub Actions builds the Docker image on every `v*` tag and publishes it to GitHub
Packages and to the `dcr.deev.su` registry.
## Development
```bash
pip install -r requirements-dev.txt
ruff check . && pytest
```
The tests (pytest-django) run in production mode and cover voting and anti-abuse, forms, escaping,
pages and static files. CI runs the same checks on every push and pull request.
## License
MIT — see [LICENSE](LICENSE).
## Author
**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
<div align="center">
<sub>⭐ If you find this project useful, give it a star on GitHub!</sub>
<p><sub>Made with ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div>

431
README.md
View file

@ -1,393 +1,128 @@
# deev.space
<div align="center">
<img src="https://img.shields.io/badge/Python-3.8+-blue.svg" alt="Python Version">
<img src="https://img.shields.io/badge/Django-4.2+-green.svg" alt="Django Version">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License">
<img src="https://img.shields.io/badge/Status-Production-brightgreen.svg" alt="Status">
</div>
**Русский** · [English](README.en.md)
Профессиональный персональный веб-сайт портфолио backend-разработчика, созданный на Django. Проект представляет собой полнофункциональную платформу с системой управления контентом, блог-системой с комментариями, интерактивным портфолио проектов и современным адаптивным дизайном.
[![CI](https://github.com/EDeev/deev.space/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/deev.space/actions/workflows/ci.yml)
[![Docker](https://github.com/EDeev/deev.space/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/deev.space/actions/workflows/docker.yml)
[![Release](https://img.shields.io/github/v/release/EDeev/deev.space)](https://github.com/EDeev/deev.space/releases)
[![License](https://img.shields.io/github/license/EDeev/deev.space)](LICENSE)
## 🌟 Основные возможности
Персональный сайт-портфолио Python-разработчика: проекты, блог, опыт и стек, оценки статей без
регистрации. Исходный код сайта [deev.space](https://deev.space).
- **Система управления контентом** через расширенную Django Admin панель с кастомными инлайнами и фильтрами
- **Блог-платформа** с поддержкой категорий, комментариев, лайков/дизлайков, галерей изображений и прикрепленных файлов
- **Портфолио проектов** с гибкой системой фильтрации по языкам программирования, технологиям и статусам
- **Страница достижений** для демонстрации наград и сертификатов
- **Многоуровневая система комментариев** с возможностью оценки и вложенности до 3 уровней
- **Интеграция с социальными сетями** для автоматической публикации новых статей в Telegram и VKontakte
- **Адаптивный дизайн** с поддержкой всех современных устройств и разрешений
- **SEO-оптимизация** включая динамический sitemap, schema.org разметку и Open Graph метатеги
- **Продвинутая аналитика** с интеграцией Яндекс.Метрики и Google Analytics
- **Безопасность** с использованием Yandex SmartCaptcha и защитой от CSRF/XSS атак
**Статус:** личный проект, активно развивается · работает на [deev.space](https://deev.space)
## 🛠 Технологический стек
![Главная страница deev.space](docs/screenshots/main.png)
**Backend:**
- Python 3.8+
- Django 4.2+
- SQLite (разработка) / PostgreSQL (продакшн)
- Pillow для обработки изображений
- Bleach для санитизации HTML
- BeautifulSoup4 для парсинга метаданных ссылок
- Requests для HTTP запросов
**Стек:** Python 3.12 · Django 4.2 · SQLite · bleach · Yandex SmartCaptcha · gunicorn + nginx · Docker
**Frontend:**
- HTML5, CSS3 с использованием CSS Custom Properties
- Vanilla JavaScript (ES6+)
- Font Awesome 6.5 для иконок
- Devicon для технологических иконок
- AOS (Animate On Scroll) для анимаций
- Prism.js для подсветки синтаксиса кода
- Google Fonts (Raleway, Inter)
## Возможности
**Интеграции:**
- Yandex SmartCaptcha для защиты форм
- Telegram Bot API для автопостинга
- VK API для публикации в группы
- Schema.org для структурированных данных
- Главная с карточкой-паспортом, стеком по категориям и блоком «В цифрах»
- Блог: категории, галереи, вложения, ссылки с автоматическим превью, комментарии с ответами
- Лайки и дизлайки без регистрации — по подписанной cookie, с лимитом оценок с одного IP
- Уникальные просмотры статей с фильтром ботов
- Проекты, достижения, опыт и образование — весь контент редактируется в админке
- Форма обратной связи с капчей и уведомлением владельцу в Telegram
- `sitemap.xml`, человекопонятные адреса, свои страницы 404 и 500
**Инфраструктура:**
- Nginx как веб-сервер и reverse proxy
- Gunicorn для WSGI сервера
- Supervisor для управления процессами
- Let's Encrypt для SSL сертификатов
## Быстрый старт
## 📁 Структура проекта
```
deev.space/
├── main/ # Основное Django приложение
│ ├── migrations/ # Миграции базы данных
│ ├── templatetags/ # Кастомные теги и фильтры
│ │ └── custom_filters.py # Фильтры для технологий, времени чтения
│ ├── models.py # Модели данных
│ ├── views.py # Представления и бизнес-логика
│ ├── forms.py # Формы с валидацией
│ ├── admin.py # Административная панель
│ ├── signals.py # Сигналы для автопостинга
│ ├── sitemaps.py # Генерация sitemap
│ ├── context_processors.py # Глобальные контекстные данные
│ └── urls.py # URL маршруты
├── dspace/ # Конфигурация Django проекта
│ ├── settings.py # Настройки приложения
│ ├── urls.py # Корневые URL паттерны
│ ├── wsgi.py # WSGI точка входа
│ └── asgi.py # ASGI точка входа
├── templates/ # HTML шаблоны
│ ├── wrapper.html # Базовый шаблон с SEO
│ ├── index.html # Главная страница
│ ├── about.html # Страница "Обо мне"
│ ├── projects.html # Портфолио проектов
│ ├── achievements.html # Достижения
│ ├── contacts.html # Контакты и форма обратной связи
│ ├── blog/ # Шаблоны блога
│ │ ├── blog.html # Список статей
│ │ └── article.html # Детальная страница статьи
│ ├── auth/ # Шаблоны аутентификации
│ │ ├── login.html # Вход
│ │ └── register.html # Регистрация
│ ├── errors/ # Страницы ошибок
│ │ ├── 404.html # Страница не найдена
│ │ └── 500.html # Ошибка сервера
│ ├── includes/ # Переиспользуемые компоненты
│ │ ├── project_card.html # Карточка проекта
│ │ ├── comments.html # Рекурсивные комментарии
│ │ └── pagination.html # Пагинация
│ └── widgets/ # Кастомные виджеты
│ └── smartcaptcha.html # Yandex SmartCaptcha
├── static/ # Статические файлы
│ ├── css/ # Стили
│ │ ├── variables.css # CSS переменные и дизайн-токены
│ │ ├── base.css # Базовые стили и типографика
│ │ ├── components.css # Переиспользуемые компоненты
│ │ ├── layout.css # Раскладка и сетки
│ │ ├── projects.css # Стили проектов
│ │ ├── blog.css # Стили блога
│ │ ├── pages.css # Страничные стили
│ │ └── media.css # Медиа-запросы
│ ├── js/ # JavaScript
│ │ └── main.js # Основная логика фронтенда
│ └── img/ # Изображения
│ ├── logo.png # Логотип
│ └── favicon.ico # Фавикон
├── media/ # Загружаемые файлы
│ ├── articles/ # Изображения статей
│ │ ├── gallery/ # Галереи статей
│ │ └── files/ # Прикрепленные файлы
│ ├── projects/ # Изображения проектов
│ ├── avatars/ # Аватары пользователей
│ └── site/ # Настройки сайта
├── logs/ # Логи приложения
├── requirements.txt # Python зависимости
├── manage.py # Django CLI утилита
└── README.md # Документация
```
## 🚀 Быстрый старт
### Предварительные требования
Перед началом работы убедитесь, что установлены следующие компоненты:
- Python 3.8 или выше
- pip (менеджер пакетов Python)
- virtualenv или venv (рекомендуется)
- Git для клонирования репозитория
### Установка и запуск
**Шаг 1. Клонирование репозитория**
```bash
git clone https://github.com/EDeev/deev.space.git
cd deev.space
git clone https://github.com/EDeev/deev.space.git && cd deev.space
cp .env.example .env # задайте DJANGO_SECRET_KEY
docker compose up -d
docker compose exec web python manage.py createsuperuser
```
**Шаг 2. Создание виртуального окружения**
```bash
python -m venv venv
# Для Linux/macOS:
source venv/bin/activate
# Для Windows:
venv\Scripts\activate
```
**Шаг 3. Установка зависимостей**
Сайт откроется на `http://localhost:8000`, админка — на `/admin/`. Готовый образ:
`docker pull ghcr.io/edeev/deev.space` или `docker pull dcr.deev.su/edeev/deev.space`.
## Установка без Docker
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
```
**Шаг 4. Настройка переменных окружения**
Создайте файл `.env` в корне проекта со следующим содержимым:
```env
# Django
DJANGO_SECRET_KEY=your-secret-key-here
DJANGO_DEBUG=True
# Email
EMAIL_HOST=smtp.yandex.ru
EMAIL_PORT=465
EMAIL_HOST_USER=your-email@example.com
EMAIL_HOST_PASSWORD=your-password
DEFAULT_FROM_EMAIL=your-email@example.com
CONTACT_EMAIL=your-email@example.com
# Yandex SmartCaptcha
SMARTCAPTCHA_CLIENT_KEY=your-client-key
SMARTCAPTCHA_SERVER_KEY=your-server-key
# Telegram (опционально)
TELEGRAM_BOT_TOKEN=your-bot-token
TELEGRAM_CHANNEL_ID=your-channel-id
# VK (опционально)
VK_ACCESS_TOKEN=your-access-token
VK_GROUP_ID=your-group-id
```
**Шаг 5. Применение миграций базы данных**
```bash
cp .env.example .env # для разработки: DJANGO_DEBUG=True
python manage.py migrate
```
**Шаг 6. Создание суперпользователя**
```bash
python manage.py populate_demo # демо-контент, по желанию
python manage.py createsuperuser
```
Следуйте инструкциям для создания учетной записи администратора.
**Шаг 7. Сбор статических файлов**
```bash
python manage.py collectstatic --noinput
```
**Шаг 8. Запуск сервера разработки**
```bash
python manage.py runserver
```
Сайт будет доступен по адресу: `http://127.0.0.1:8000`
## Конфигурация
Административная панель: `http://127.0.0.1:8000/admin`
Все настройки — переменные окружения (полный список — [`.env.example`](.env.example)):
## 📊 Модели данных
| Переменная | Назначение |
|---|---|
| `DJANGO_SECRET_KEY` | секретный ключ Django, обязателен при `DJANGO_DEBUG=False` |
| `DJANGO_DEBUG` | режим отладки, по умолчанию `False` |
| `DJANGO_ALLOWED_HOSTS`, `DJANGO_CSRF_TRUSTED_ORIGINS` | домены сайта через запятую |
| `DJANGO_DB_PATH`, `DJANGO_MEDIA_ROOT` | где лежат база SQLite и загруженные файлы |
| `SMARTCAPTCHA_CLIENT_KEY`, `SMARTCAPTCHA_SERVER_KEY` | Yandex SmartCaptcha для формы обратной связи |
| `EMAIL_*`, `CONTACT_EMAIL` | отправка писем с формы обратной связи |
| `ALERTBOT_TOKEN`, `ALERTBOT_CHAT_ID` | уведомление владельцу в Telegram о новом сообщении |
| `SOCIAL_AUTOPOST`, `TELEGRAM_*`, `VK_*` | автопостинг новых статей, по умолчанию выключен |
### SiteSettings (Настройки сайта)
Singleton модель для управления глобальными настройками сайта через административную панель. Включает информацию о владельце, контакты, социальные сети и файлы.
> [!IMPORTANT]
> С `DJANGO_DEBUG=False` сайт включает HSTS и редирект на HTTPS. Для запуска без TLS (локально или за
> прокси, который сам терминирует HTTPS) задайте `DJANGO_SECURE_SSL_REDIRECT=False`.
**Основные поля:**
- `site_name`, `site_description` - название и описание сайта
- `owner_name`, `owner_title`, `owner_bio` - информация о владельце
- `owner_photo` - фотография
- `owner_email`, `owner_phone`, `owner_city` - контактные данные
- `telegram_url`, `github_url`, `vk_url`, `linkedin_url` - социальные сети
- `resume_file` - файл резюме
## Как выглядит
### Article (Статьи блога и достижения)
Универсальная модель для статей блога и достижений с поддержкой мультимедиа контента.
| О себе | Проекты |
|---|---|
| ![О себе](docs/screenshots/about.png) | ![Проекты](docs/screenshots/projects.png) |
| **Блог** | **Мобильная версия** |
| ![Блог](docs/screenshots/blog.png) | ![Мобильная версия](docs/screenshots/mobile.png) |
**Основные поля:**
- `title`, `slug`, `sub_title` - заголовки и URL
- `excerpt`, `post` - описание и содержание
- `img` - превью изображение
- `category` - категория статьи
- `is_published` - статус публикации
- `comments_enabled` - включение комментариев
- `is_achievement` - флаг достижения
- `views`, `date`, `updated_at` - метаданные
## Как устроено
**Связанные модели:**
- `ArticleImage` - галерея изображений
- `ArticleFile` - прикрепленные файлы
- `ArticleLink` - прикрепленные ссылки с автоматическим парсингом метаданных
### Project (Портфолио проектов)
Модель для управления проектами с гибкой системой статусов и отображения.
**Основные поля:**
- `title`, `slug` - название и URL
- `short_description`, `description` - описания
- `features` - список особенностей
- `programming_languages` - языки программирования
- `technologies` - используемые технологии
- `status` - связь с ProjectStatus
- `card_size` - размер карточки (featured/regular/small)
- `show_on_homepage`, `homepage_order` - отображение на главной
- `github_url`, `demo_url` - ссылки
### Experience (Опыт работы)
Детальная информация о профессиональном опыте.
**Основные поля:**
- `title`, `company`, `company_url` - должность и компания
- `description`, `responsibilities` - описание и обязанности
- `technologies` - используемые технологии
- `start_date`, `end_date`, `is_current` - период работы
- Автоматический расчет продолжительности через свойство `duration`
### Education (Образование)
Информация об образовании с поддержкой различных типов.
**Основные поля:**
- `institution`, `degree` - учебное заведение и специальность
- `education_type` - тип (университет/курс/школа)
- `achievements` - список достижений
- `start_year`, `end_year`, `is_current` - период обучения
- `certificate_number`, `certificate_url` - сертификаты
### Comment (Комментарии)
Многоуровневая система комментариев с поддержкой вложенности.
**Основные поля:**
- `article`, `user`, `parent` - связи
- `content` - содержание комментария
- `is_approved` - модерация
- Автоматический расчет уровня вложенности через `nesting_level`
- Подсчет лайков/дизлайков через `CommentLike`
### CustomUser (Пользователи)
Расширенная модель пользователя Django.
**Дополнительные поля:**
- `email` - опциональный email
- `is_verified` - статус верификации
- `avatar` - аватар пользователя
## ⚙️ Конфигурация
### Основные настройки производства
Для развертывания в продакшн среде необходимо изменить следующие параметры в `dspace/settings.py`:
```python
# Безопасность
DEBUG = False
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
ALLOWED_HOSTS = ['deev.space', 'www.deev.space']
# База данных (рекомендуется PostgreSQL)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'deevspace_db',
'USER': 'deevspace_user',
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': 'localhost',
'PORT': '5432',
}
}
# Безопасность
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
```mermaid
flowchart LR
B[Браузер] --> N[nginx<br/>TLS, static, media]
N --> G[gunicorn]
G --> D[Django: main]
D --> S[(SQLite)]
D -.-> T[Telegram / AlertBot]
D -.-> C[Yandex SmartCaptcha]
```
### Настройка интеграций
Одно приложение `main`: модели контента, оценок и настроек сайта, классовые представления, JSON-API
для оценок и комментариев, middleware анонимного посетителя. Подробности:
**Автопостинг в Telegram:**
Настройте переменные окружения `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHANNEL_ID`. При публикации новой статьи автоматически отправляется пост в канал.
- [docs/architecture.md](docs/architecture.md) — модели, оценки без регистрации, антинакрутка, безопасность
- [docs/deploy.md](docs/deploy.md) — запуск в Docker и как устроен боевой сервер
**Автопостинг в VKontakte:**
Настройте `VK_ACCESS_TOKEN` и `VK_GROUP_ID` для автоматической публикации в группу VK.
## Развёртывание
**Email уведомления:**
Настройте SMTP параметры для отправки уведомлений через контактную форму.
[deev.space](https://deev.space) работает на VPS: gunicorn под отдельным пользователем за nginx с
сертификатом Let's Encrypt, статика и загрузки отдаются nginx. Доступность и срок сертификата
отслеживает Prometheus. Docker-образ собирает GitHub Actions на каждый тег `v*` и публикует в GitHub
Packages и в реестр `dcr.deev.su`.
## 🌐 Развертывание
## Разработка
Можете прочитать о развёртывании проекта на сервере в <a href="https://deev.space/blog/razvertyvanie-django-proekta-na-servere-s-nulya-do-https/">статье на моём сайте</a>.
```bash
pip install -r requirements-dev.txt
ruff check . && pytest
```
## 📈 Аналитика и мониторинг
Тесты (pytest-django) запускаются в боевом режиме: голосование и антинакрутка, формы, экранирование,
страницы и статика. CI выполняет то же самое на каждый push и pull request.
Проект интегрирован с системами аналитики для отслеживания поведения пользователей:
## Лицензия
**Яндекс.Метрика:**
Автоматически загружается при наличии `YANDEX_METRIKA_ID` в настройках. Отслеживает посещаемость, карты кликов, вебвизор и другие метрики.
MIT — см. [LICENSE](LICENSE).
**Google Analytics:**
Подключается при указании `GOOGLE_ANALYTICS_ID`. Предоставляет детальную аналитику трафика и поведения пользователей.
## Автор
**Логирование:**
Настроено детальное логирование с записью ошибок в файлы и вывод информационных сообщений в консоль.
## 🛡️ Безопасность
Проект реализует следующие меры безопасности:
- **CSRF Protection** - защита от межсайтовых запросов через Django middleware
- **XSS Protection** - санитизация пользовательского ввода с помощью Bleach
- **SQL Injection Protection** - использование Django ORM
- **Yandex SmartCaptcha** - защита форм от ботов
- **HTTPS Redirect** - принудительное перенаправление на защищенное соединение
- **HSTS Headers** - заголовки безопасности для браузеров
- **Secure Cookies** - защищенные cookies для сессий
- **Content Security Policy** - настроенные заголовки безопасности
- **Rate Limiting** - защита от перегрузки (рекомендуется настроить на уровне Nginx)
## 👨‍💻 Автор и контакты
**Деев Егор Викторович**
Backend Developer | Python Specialist
- **Веб-сайт:** [deev.space](https://deev.space)
- **GitHub:** [@EDeev](https://github.com/EDeev)
- **Email:** egor@deev.space
- **Telegram:** [@Egor_Deev](https://t.me/Egor_Deev)
## 📄 Лицензия
Этот проект является некоммерческим и распространяется под лицензией MIT.
**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
<div align="center">
<sub>⭐ Если проект оказался полезным, поставьте звездочку на GitHub!</sub>
<p><sub>Создано с ❤️ от вашего дорогого - <a href="https://deev.space">deev.space</a> ©</sub></p>
<sub>⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!</sub>
<p><sub>Сделано с ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div>

51
docs/architecture.md Normal file
View file

@ -0,0 +1,51 @@
# Как устроен deev.space
Django-проект `dspace` с одним приложением `main`. База — SQLite, статика — whitenoise (в бою — nginx),
шаблоны — Django templates, без фронтенд-фреймворков.
```
dspace/ настройки, корневые URL, WSGI
main/
models.py модели контента, оценок и настроек сайта
views.py страницы (классовые представления) и JSON-API оценок и комментариев
forms.py формы с очисткой HTML (bleach) и Yandex SmartCaptcha
middleware.py анонимный ID посетителя, хэш IP, фильтр ботов
signals.py действия после публикации статьи (автопостинг, ping Яндекса)
admin.py админка с превью и инлайнами медиа статьи
management/ load_initial_data, populate_demo
templates/ шаблоны страниц, включая includes/ и errors/
static/ CSS по слоям (variables, base, components, layout, pages, media), JS
```
## Модели
| Модель | Назначение |
|---|---|
| `SiteSettings` | синглтон с текстами сайта, контактами, карточкой-паспортом (`SiteSettings.load()`) |
| `CustomUser` | пользователь для комментариев, упрощённая регистрация |
| `Category`, `Article` | статьи блога и достижения (`is_achievement`); slug генерируется из заголовка |
| `ArticleImage`, `ArticleFile`, `ArticleLink` | галерея, вложения и ссылки статьи; у ссылок — автоматическое превью по Open Graph |
| `Project`, `ProjectStatus` | проекты портфолио с гибкими статусами |
| `Skill`, `Experience`, `Education` | стек по категориям, опыт и образование |
| `Comment` | комментарии с ответами до трёх уровней вложенности |
| `ArticleLike`, `CommentLike` | лайки и дизлайки — от пользователя или анонимного посетителя |
| `ArticleView` | уникальный просмотр статьи (один на посетителя) |
| `ContactMessage` | сообщения с формы обратной связи |
## Оценки без регистрации
1. `VisitorMiddleware` выдаёт каждому посетителю подписанную cookie `dspace_vid` (uuid4, httponly, год).
2. Голос привязан к аккаунту, если пользователь вошёл, иначе — к `visitor_id`. Повторный клик снимает
голос, клик по противоположной кнопке меняет его.
3. Антинакрутка: с одного хэша «IP + User-Agent» (соль — `SECRET_KEY`) — не больше двух новых
анонимных оценок одного объекта в сутки. Для loopback и частных адресов хэш не считается, лимит не
применяется.
4. Уникальные просмотры (`ArticleView`) пишутся только для посетителей, которых `is_bot()` не
считает роботами.
## Безопасность
- HTML комментариев проходит через `bleach` (белый список тегов), из формы обратной связи вырезается весь.
- Форма обратной связи защищена Yandex SmartCaptcha.
- Превью ссылок загружаются только с публичных http(s)-адресов.
- С `DJANGO_DEBUG=False`: HSTS, редирект на HTTPS, secure-cookie; без `DJANGO_SECRET_KEY` запуск невозможен.

32
docs/deploy.md Normal file
View file

@ -0,0 +1,32 @@
# Развёртывание
## Docker
```bash
cp .env.example .env # задайте DJANGO_SECRET_KEY и при необходимости ключи капчи и почты
docker compose up -d
docker compose exec web python manage.py createsuperuser
```
База и загруженные файлы хранятся в томе `data` (`/data/db.sqlite3`, `/data/media`). Готовый образ
собирается GitHub Actions на каждый тег `v*`:
```bash
docker pull ghcr.io/edeev/deev.space:latest
docker pull dcr.deev.su/edeev/deev.space:latest
```
За обратным прокси укажите домены в `DJANGO_ALLOWED_HOSTS` и `DJANGO_CSRF_TRUSTED_ORIGINS`, а
`DJANGO_SERVE_MEDIA` выключите и отдавайте `/media/` прокси-сервером.
## Как работает deev.space
Боевой сайт крутится на VPS без Docker:
- gunicorn под отдельным пользователем `dspace`, systemd-юнит, unix-сокет;
- nginx отдаёт `/static/` и `/media/` с диска и проксирует остальное в сокет, TLS — Let's Encrypt;
- переменные окружения — в `.env` рядом с проектом;
- обновление: выложить код, `pip install -r requirements.txt`, `python manage.py migrate`,
`python manage.py collectstatic --noinput`, перезапуск юнита;
- доступность сайта и срок сертификата проверяет Prometheus (blackbox exporter), уведомления
о новых сообщениях с формы приходят в Telegram через AlertBot.

BIN
docs/screenshots/about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

BIN
docs/screenshots/blog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
docs/screenshots/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

BIN
docs/screenshots/mobile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB