Skip to content

Repository files navigation

Portfolio CMS Template

Обезличенный шаблон персонального сайта-портфолио на FastAPI с серверным рендерингом через Jinja2, хранением контента в базе данных и собственной административной панелью.

О проекте

Проект задуман не как статический лендинг, а как небольшое CMS-подобное приложение:

  • публичная часть показывает профиль, навыки и проекты;
  • контент хранится в базе данных;
  • админка позволяет управлять основными блоками сайта без изменения кода;
  • архитектура остается простой и понятной для дальнейшего сопровождения.

Репозиторий специально подготовлен для публичного размещения:

  • без личных данных владельца;
  • без реальных контактов;
  • без стартовых реальных проектов в seed.py.

На текущем этапе реализованы:

  • публичная главная страница;
  • список проектов;
  • детальные страницы проектов;
  • парольная авторизация в админке;
  • редактирование профиля;
  • CRUD для контактов;
  • CRUD для категорий навыков и отдельных навыков;
  • CRUD для проектов;
  • ограничение до 3 избранных проектов на главной странице.

Технологии

  • Python
  • FastAPI
  • SQLAlchemy 2.x
  • Jinja2
  • SQLite
  • Pydantic Settings
  • Starlette SessionMiddleware

Структура проекта

portfolio/
├─ app/
│  ├─ config.py
│  ├─ database.py
│  ├─ dependencies.py
│  ├─ main.py
│  ├─ seed.py
│  ├─ models/
│  │  ├─ contact.py
│  │  ├─ profile.py
│  │  ├─ project.py
│  │  └─ skill.py
│  ├─ routers/
│  │  ├─ public.py
│  │  ├─ admin_auth.py
│  │  ├─ admin_profile.py
│  │  ├─ admin_contacts.py
│  │  ├─ admin_skills.py
│  │  └─ admin_projects.py
│  ├─ services/
│  │  └─ site_content.py
│  ├─ static/
│  │  ├─ css/
│  │  └─ images/
│  └─ templates/
├─ requirements.txt
├─ PROJECT_CONTEXT.md
├─ ARCHITECTURE.md
├─ DEPLOY.md
└─ README.md

Архитектурная логика

1. Точка входа

Файл app/main.py:

  • создает экземпляр FastAPI;
  • подключает middleware для сессий;
  • монтирует статику;
  • подключает все роутеры;
  • на старте создает таблицы и при пустой базе выполняет начальное заполнение.

2. Конфигурация

Файл app/config.py отвечает за настройки приложения:

  • database_url
  • admin_password
  • secret_key

Все значения могут браться из .env.

3. База данных

Файл app/database.py:

  • создает engine;
  • описывает базовый класс Base для всех ORM-моделей;
  • создает SessionLocal;
  • предоставляет dependency get_db() для роутеров.

4. Модели

Profile

Одна запись с основной информацией о владельце сайта:

  • ФИО
  • должность
  • подзаголовок
  • текст "О себе"
  • путь к фото

Contact

Контактная информация, связанная с профилем:

  • тип
  • название
  • значение
  • ссылка
  • порядок отображения

SkillCategory

Категория навыков, например:

  • Backend
  • AI
  • Infrastructure
  • Integrations

Skill

Отдельный навык внутри категории.

Project

Карточка проекта для публичной части и админки.

5. Сервисный слой

app/services/site_content.py собирает данные для главной страницы:

  • профиль;
  • контакты;
  • категории навыков;
  • избранные проекты.

Это позволяет не дублировать одинаковые ORM-запросы между публичной и админской версиями главной страницы.

6. Роутеры

Публичные

app/routers/public.py

  • /
  • /projects
  • /projects/{slug}

Админка

Роутеры админки разделены по ответственности:

  • admin_auth.py — вход и выход;
  • admin_profile.py — главная админки и редактирование профиля;
  • admin_contacts.py — CRUD контактов;
  • admin_skills.py — CRUD категорий навыков и навыков;
  • admin_projects.py — CRUD проектов.

Как запустить локально

1. Установить зависимости

python -m pip install -r requirements.txt

2. Создать .env

Пример:

DATABASE_URL=sqlite:///./portfolio.db
ADMIN_PASSWORD=your-strong-password
SECRET_KEY=your-long-random-secret

3. Запустить приложение

python -m uvicorn app.main:app --reload

После запуска будут доступны:

  • http://127.0.0.1:8000/
  • http://127.0.0.1:8000/projects
  • http://127.0.0.1:8000/admin

Запуск через Docker Compose

Для серверного или production-like запуска проект можно поднимать через docker compose.

1. Создать .env

Пример:

DATABASE_URL=sqlite:////srv/portfolio/data/portfolio.db
ADMIN_PASSWORD=change-this-password
SECRET_KEY=change-this-secret-key

2. Поднять контейнер

docker compose up -d --build

3. Проверить контейнер

docker ps
docker logs portfolio_web --tail 50

4. Где будут храниться данные

docker-compose.yml монтирует два каталога:

  • ./data -> /srv/portfolio/data
  • ./uploads -> /srv/portfolio/app/static/uploads

Это значит, что:

  • база SQLite хранится на хосте;
  • загруженные фото и изображения проектов тоже хранятся на хосте;
  • пересборка контейнера не удаляет контент.

Что поменять на свои данные

После клонирования репозитория настрой проект под себя в таком порядке:

  1. Обнови .env:
    • ADMIN_PASSWORD
    • SECRET_KEY
    • при необходимости DATABASE_URL
  2. Запусти приложение.
  3. Зайди в /admin/login.
  4. В /admin/profile/edit замени placeholder-данные:
    • имя;
    • роль;
    • подзаголовок;
    • текст "О себе";
    • фото профиля.
  5. Через /admin/contacts добавь свои контакты.
  6. Через /admin/skills добавь категории навыков и сами навыки.
  7. Через /admin/projects добавь реальные проекты и загрузки изображений.

Такой сценарий удобен для публичного GitHub-репозитория: код открыт, а реальный контент живет только в твоей локальной или серверной базе данных.

Если до этого ты уже запускал проект со старой сидированной базой, удали portfolio.db и запусти приложение снова, чтобы получить чистый обезличенный старт.

Начальное заполнение базы

Файл app/seed.py заполняет пустую базу только базовым placeholder-профилем.

Важно:

  • сидирование выполняется только если в базе еще нет профиля;
  • если структура модели изменилась и нужны новые поля в SQLite, проще удалить portfolio.db и дать приложению создать базу заново;
  • реальный контент рекомендуется вносить уже через админку.

Маршруты

Публичные

  • / — главная страница
  • /projects — список всех проектов
  • /projects/{slug} — детальная страница проекта

Админка

  • /admin/login — вход
  • /admin/logout — выход
  • /admin — админская версия главной страницы
  • /admin/profile/edit — редактирование профиля
  • /admin/contacts — управление контактами
  • /admin/skills — управление навыками
  • /admin/projects — управление проектами

Особенности текущей реализации

Ограничение избранных проектов

На главной странице выводятся только 3 избранных проекта.

В админке это ограничение поддерживается на уровне серверной логики:

  • нельзя сохранить четвертый проект как is_featured=True;
  • пользователь получает понятную ошибку прямо в форме проекта.

Картинки проектов

Изображения проектов теперь можно загружать через админку.

Что можно развивать дальше

  • отдельное редактирование фото профиля;
  • валидация slug и URL;
  • более строгие сообщения об ошибках в формах;
  • Dockerfile и docker-compose;
  • деплой на VPS с Nginx;
  • обновление SSL-сертификата для домена.

Важная заметка по сопровождению

Чтобы быстро вспомнить логику проекта через месяц:

  • начни с README.md;
  • потом открой app/main.py;
  • затем посмотри app/services/site_content.py;
  • после этого роутеры в app/routers/;
  • и уже потом модели в app/models/.

Так проще всего восстановить общую картину: сначала вход в приложение, потом поток данных, потом конкретные CRUD-блоки.

Где обычно меняют данные под себя

  • .env — пароль админа, secret_key, строка подключения к БД;
  • app/seed.py — только стартовый placeholder-профиль;
  • app/static/uploads/profile/ — загруженные фото профиля;
  • app/static/uploads/projects/ — загруженные изображения проектов;
  • portfolio.db — весь контент, добавленный через админку.

About

My portfolio site. FastAPI.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages