Тудушка, которая переросла в соцсеть: два пет-проекта на FastAPI с реальными пользователями
Привет всем, только недавно зарегистрировался на этой платформе. За предыдущий месяц сделал два проекта на FastAPI, хотелось бы узнать чужое мнение:
Менеджер мероприятий

Архитектура проекта:
C:.
│ alembic.ini
│ audit.py
│ auth.py
│ config.py
│ database.py
│ events.db
│ googleb487f7db970152b3.html
│ main.py
│ models.py
│ README.md
│ requirements.txt
│ structure.txt
│ taskrepo.py
│ taskservice.py
│ test.db
│ yandex_12353e0b4137cb06.html
├───tasks
│ │ tasks.py
│ │ __init__.py
│
├───templates
│ deletemenu.html
│ global.html
│ history.html
│ info.html
│ llist.html
│ mainpage.html
│ meet.png
│ reglog.html
│ search.html
│ searchmenu.html
│ searchRESULT.html
│ statistics.html
│ topmenu.html
│ uved.html
│
├───tests
│ │ test_events.pyКогда мне предложили сделать такой проект, я подумал, что это та же самая тудушка, только слегка изменённая. Однако, я начал добавлять фичи, и это стало больше, чем просто пет-проект.
В функции, доступные пользователю я могу отнести: авторизация, создание и редактирование мероприятий, добавление участников(юзеры должны сами записаться, нельзя просто так кого-то добавить), поиск мероприятий по тегам, уведомления между пользователями, статистика, история действий аккаунта и функция ставления лайков под мероприятием.
Для безопасности я использовал jwt токены и хеширование паролей при добавлении их в БД. На удивление, я много времени потратил на то, чтобы проверка и добавление хешированных паролей правильно работали, потому что я не декодировал хешированный пароль перед тем, как добавить его в БД. Вот как теперь выглядит функция в файле репозитория:
def add_user(self, name,password):
salt=bcrypt.gensalt()
hashed=bcrypt.hashpw(password=password.encode(encoding='utf-8'), salt=salt) #хешированный пароль
hashed=hashed.decode('utf-8') #декодированние пароля
target=User(name=name, password=hashed)
self.db.add(target) # запись в БД
self.db.commit()
return targetТакже, что сделало из моего пет-проекта во что-то большее, но и заняло довольно много времени это взаимодействие с юзерами. Раньше участники мероприятий были просто текстом и настоящего нельзя было добавить. Чтобы это исправить, я убрал класс Участников, и вместо него сделал связку многие-ко-многим между пользователями и мероприятиями.
participants = Table(
"participants",
Base.metadata,
Column("user_id", Integer, ForeignKey("users.id"), primary_key=True),
Column("event_id", Integer, ForeignKey("events.id"), primary_key=True),
)После этого, стало проще придумывать новые фичи, и проект стал напоминать некую соц сеть.
В качестве БД я использовал SQLite до деплоя, но после перешел на Postgres - как по мне, лучший вариант для продакшена(использовал эту БД для всех своих проектов).
Использованные библиотеки: Jose, Bcrypt, sqlalchemy, FastAPI, Datetime
Ссылка на репозиторий: https://github.com/RobertAvdeenkov/Meetly
Ссылка на сайт: https://meetly-n865.onrender.com
Форум

Архитектура проекта:
C:.
│ alembic.ini
│ auth.py
│ config.py
│ database.py
│ forum.db
│ forumDB.db
│ forumDB.sqbpro
│ main.py
│ models.py
│ README.md
│ requirements.txt
│ task_repo.py
│ task_service.py
│ test_forum.db
│
├───tasks
│ │ tasks.py
│
├───templates
│ create.html
│ info.html
│ menu.html
│ postMenu.html
│ profile.html
│ reglog.html
│ search.html
│
├───tests
│ │ test_forum.pyПланировал на этом проекте набить руку, но в процессе разработки понял, что он будет отличаться от простых тудушек. Проект рабочий, но это только MVP форума.
Количество функций по сравнению с планировщиком уже скудно: авторизация, создание и удаление постов, система лайков и комментариев и поиск по категориям и профиль, доступный только самому пользователю.
Как и с прошлым проектом использовал я токены, но теперь я начал их хранить в куках. Это была одна из причин, почему я начал делать проект. Также если посмотреть на код планировщика и код форума, разница очень заметная. Код стал намного чище и понятнее, и это благодаря всего лишь одной функции:
def get_by_token(token:str):
try:
data=jwt.decode(token,SECRET, algorithms=[ALGORITHM]) #проверка токена
return data['sub']
except ExpiredSignatureError: #если токен просрочен
raise HTTPException(401, 'Токен протух!')
except JWTError: #если поддельный токен
raise HTTPException(401, 'Неверный токен')Дело в том, что в планировщике я использовал конструкцию try/except чуть ли не в каждом эндпоинте(я потом исправил этот недочет), а потом просто добавил функцию проверки токена(наверное, звучит тупо, но для меня это было открытием). И в конечном итоге я сократил код на 80 строк!
Использованные библиотеки: Jose, Bcrypt, sqlalchemy, FastAPI, Datetime, Alembic
Ссылка на репозиторий: https://github.com/RobertAvdeenkov/TellnAsk
Ссылка на сайт: https://tellnask.onrender.com
В качестве хостинга я выбрал Render, потому бесплатного тарифа вполне хватает для пет-проектов. БД я брал из Neon и Supabase, потому что тоже есть бесплатный тариф.
Также хотел поинтересоваться: Если вы посмотрите мой код, то увидите N+1 проблему. Как она решается?
Очень рекомендую заходить на проекты с ВПН, потому у Render есть распространенная ошибка блокировки определенного региона при переходе на сайт. К сожалению, на бесплатном тарифе я не могу привязать свой домен, чтобы не возвращаться к проблеме. Пишите комментарии, если есть какие-то баги или другие проблемы. Буду только рад. Также хотелось бы услышать идеи для новых проектов под мой стек)