https://medium.com/@lautisuarez081/fastapi-best-practices-and-design-patterns-building-quality-python-apis-31774ff3c28a
FastAPI bilan SOLID prinsiplariga mos va best practicelar asosida APi yozish bo'yicha maqola
FastAPI bilan SOLID prinsiplariga mos va best practicelar asosida APi yozish bo'yicha maqola
Medium
FastAPI Best Practices and Design Patterns: Building Quality Python APIs
In recent years, FastAPI has emerged as one of the most popular frameworks for building Python APIs thanks to its simplicity, speed and…
FastAPI SQLAlchemy 2.0 bilan (Type-Annotated, ya'ni Mapped va mapped_column) sintaksisida relationshiplarni ko'rib chiqamiz: 👇
1. One-to-Many (Birga ko'p) va Foreign KeyMantiq: Bir foydalanuvchi (User) ko'plab maqolalar (Post) yozishi mumkin.
from typing import List
from sqlalchemy import ForeignKey, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
pass
# 1. USER (Bir)
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(String(50))
# Python darajasidagi bog'lanish (Ko'p bo'lgani uchun List olinadi)
posts: Mapped[List["Post"]] = relationship(back_populates="author")
# 2. POST (Ko'p)
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
# Baza darajasida bog'lanish (Foreign Key)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
# Python darajasidagi bog'lanish (Faqat bitta obyekt)
author: Mapped["User"] = relationship(back_populates="posts")
2. One-to-One (Birga bir)Mantiq: Har bir foydalanuvchining (User) faqat bitta profili (Profile) bo'ladi.SQLAlchemy 2.0 da One-to-One qilish uchun ForeignKey qo'yilgan ustunni unikal (unique=True) qilish va munosabat turini to'g'ri ko'rsatish kifoya.
class Profile(Base):
__tablename__ = "profiles"
id: Mapped[int] = mapped_column(primary_key=True)
bio: Mapped[str] = mapped_column(String(255))
# Foreign Key unikal (unique=True) bo'lishi shart!
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), unique=True)
# Har ikki tomonda ham List ishlatilmaydi, chunki munosabat 1:1
user: Mapped["User"] = relationship(back_populates="profile")
# 💡 Diqqat: Yuqoridagi User modeliga quyidagi qatorni qo'shib qo'yish kerak:
# profile: Mapped["Profile"] = relationship(back_populates="user")
3. Many-to-Many (Ko'pga ko'p) va Oddiy Oraliq TableMantiq: Maqola (Post) ko'plab teglarga (Tag) ega bo'lishi mumkin. Ustunlar faqat ID-lardan iborat bo'lgani uchun Table obyektidan foydalanamiz.
from sqlalchemy import Table, Column
# 1. ORALIQ JADVAL (Faqat ID'larni saqlaydi)
post_tag_m2m = Table(
"post_tag_association",
Base.metadata,
Column("post_id", ForeignKey("posts.id"), primary_key=True),
Column("tag_id", ForeignKey("tags.id"), primary_key=True),
)
# 2. TAG JADVALI
class Tag(Base):
__tablename__ = "tags"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
# secondary orqali oraliq jadval ko'rsatiladi
posts: Mapped[List["Post"]] = relationship(secondary=post_tag_m2m, back_populates="tags")
# 3. POST JADVALI (Yuqoridagi Post modelini kengaytiramiz)
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
author: Mapped["User"] = relationship(back_populates="posts")
# Teglar bilan Many-to-Many bog'lanish
tags: Mapped[List[Tag]] = relationship(secondary=post_tag_m2m, back_populates="posts")
4. Many-to-Many orqali qo'shimcha ma'lumot saqlash (Association Object)Mantiq: Talaba (Student) va Kurs (Course). Biz talaba kursga qachon yozilganini (enrolled_at) ham saqlamoqchimiz.Bunda oraliq jadval to'laqonli modelga (Base klasiga) aylanadi va ikkita One-to-Many munosabati kabi yoziladi.
from datetime import datetime
from sqlalchemy import func
# 1. KENGAYTIRILGAN ORALIQ MODEL
class Enrollment(Base):
__tablename__ = "enrollments"
student_id: Mapped[int] = mapped_column(ForeignKey("students.id"), primary_key=True)
course_id: Mapped[int] = mapped_column(ForeignKey("courses.id"), primary_key=True)
# Qo'shimcha ustun (Masalan: yozilgan vaqti)
enrolled_at: Mapped[datetime] = mapped_column(default=func.now())
# Har ikki modelga munosabat (relationship)
student: Mapped["Student"] = relationship(back_populates="course_associations")
course: Mapped["Course"] = relationship(back_populates="student_associations")
# 2. STUDENT MODELI
class Student(Base):
__tablename__ = "students"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
# Kurslarga oraliq model orqali boriladi
course_associations: Mapped[List["Enrollment"]] = relationship(back_populates="student")
# 3. COURSE MODELI
class Course(Base):
__tablename__ = "courses"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
# Talabalarga oraliq model orqali boriladi
student_associations: Mapped[List["Enrollment"]] = relationship(back_populates="course")
💡 FastAPI uchun muhim eslatma (N+1 muammosi)FastAPI asinxron (asyncio) ishlaganda, munosabatlarni chaqirishda xatolik (MissingGreenlet) bermasligi uchun query yozayotganda ma'lumotlarni srazi qo'shib yuklab olish lozim (lazy="selectin" yoki selectinload yordamida)💡️️
from sqlalchemy.orm import selectinload
from sqlalchemy.future import select
# API endpoint ichida ishlatilishi:
stmt = select(Post).options(selectinload(Post.author)).where(Post.id == 1)
result = await db.execute(stmt)
post = result.scalar_one()
print(post.author.username) # Muammosiz ishlaydi
alembic init qilingandan keyin agar database asinxron bo'lsa alembic migration qilishda xatolik bo'lmasligi uchun alembic/env.pyni asinxronga o'tkazish:
alembic.ini faylida ham postgresql+asyncpg ishlatiladi
from __future__ import annotations
import asyncio
from logging.config import fileConfig
from alembic import context
from sqlalchemy import pool
from sqlalchemy.ext.asyncio import create_async_engine
from database import Base
# Import all model modules so metadata is populated before autogenerate.
# Replace this import with your project package if needed.
import models # noqa: F401
config = context.config
if config.config_file_name is not None:
fileConfig(config.config_file_name)
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""Run migrations without DB connection."""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
compare_type=True,
compare_server_default=True,
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection) -> None:
context.configure(
connection=connection,
target_metadata=target_metadata,
compare_type=True,
compare_server_default=True,
)
with context.begin_transaction():
context.run_migrations()
async def run_migrations_online() -> None:
"""Run migrations through async engine, but execute Alembic sync core via run_sync."""
connectable = create_async_engine(
config.get_main_option("sqlalchemy.url"),
poolclass=pool.NullPool,
)
try:
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
finally:
await connectable.dispose()
if context.is_offline_mode():
run_migrations_offline()
else:
asyncio.run(run_migrations_online())
alembic.ini faylida ham postgresql+asyncpg ishlatiladi
FastAPI da xuddi djangodagidek Choice yozish uchun quyidagidek yozish kerak:
Shunda masalan admin <- bu dbga yoziladigani Admin Adminstrator esa frontendda ko'rsatiladigan sifatida ishlatish mumkin bo'ladi.
# Frontend barcha ro'yxatni ("choices") olmoqchi bo'lsa:
class RoleChoice(str, Enum):
# (backend_value, frontend_label)
ADMIN = ("admin", "Admin Administrator")
EDITOR = ("editor", "Redaktor / Muharrir")
USER = ("user", "Oddiy foydalanuvchi")
def __new__(cls, value, label):
obj = str.__new__(cls, value)
obj._value_ = value
obj.label = label
return obj
Shunda masalan admin <- bu dbga yoziladigani Admin Adminstrator esa frontendda ko'rsatiladigan sifatida ishlatish mumkin bo'ladi.
# Frontend barcha ro'yxatni ("choices") olmoqchi bo'lsa:
@app.get("/roles")
async def get_roles():
return [
{"value": role.value, "label": role.label}
for role in RoleChoice
]https://fastapicloud.com/
Fastapi loyihani terminalda bitta command bilan deploy qilsa bo'ladigan website
Fastapi loyihani terminalda bitta command bilan deploy qilsa bo'ladigan website
uv run fastapi deploy
FastAPI Cloud
Deploy FastAPI apps to the cloud in one single command. You code. We cloud.
Forwarded from Библиотека питониста | Python, Django, Flask
😯 FastAPI Cloud вышел в публичную бету
Деплой существующего FastAPI-приложения:
Новое приложение:
🚀 Что включено из коробки
— HTTPS по умолчанию — автоматические TLS-сертификаты
— Автоскейлинг — растёт с трафиком, scale to zero в разработке
— Zero-downtime деплои — новые версии раскатываются постепенно
— Авто-верификация — если что-то сломалось, остаётся последняя рабочая версия
— GitHub интеграция — push в main = автодеплой, без CI-конфигов
— БД из коробки — Neon (Postgres), Redis Cloud, Supabase в пару кликов
— Логи, метрики, переменные окружения, кастомные домены
— VS Code расширение
⚙️ GitHub Actions если нужно
Команда сама создаёт deploy tokens, прописывает их как GitHub secrets и генерирует workflow файл.
🤖 Про агентов
CLI спроектирован так чтобы AI-агенты могли работать с ним из терминала — деплоить, читать логи, обновлять переменные, дебажить — без кастомных интеграций. Поддержка JSON-вывода, явные параметры.
Вместо стен YAML — одна команда
Ссылка на сайт
📍 Навигация: Вакансии • Задачи • Собесы
Библиотека питониста
#буст
Деплой существующего FastAPI-приложения:
uv run fastapi deploy
Новое приложение:
uvx fastapi-new
uv run fastapi deploy
🚀 Что включено из коробки
— HTTPS по умолчанию — автоматические TLS-сертификаты
— Автоскейлинг — растёт с трафиком, scale to zero в разработке
— Zero-downtime деплои — новые версии раскатываются постепенно
— Авто-верификация — если что-то сломалось, остаётся последняя рабочая версия
— GitHub интеграция — push в main = автодеплой, без CI-конфигов
— БД из коробки — Neon (Postgres), Redis Cloud, Supabase в пару кликов
— Логи, метрики, переменные окружения, кастомные домены
— VS Code расширение
⚙️ GitHub Actions если нужно
fastapi cloud setup-ci
Команда сама создаёт deploy tokens, прописывает их как GitHub secrets и генерирует workflow файл.
🤖 Про агентов
CLI спроектирован так чтобы AI-агенты могли работать с ним из терминала — деплоить, читать логи, обновлять переменные, дебажить — без кастомных интеграций. Поддержка JSON-вывода, явные параметры.
Вместо стен YAML — одна команда
fastapi deploy. Это и есть deployment surface для агентов.Ссылка на сайт
📍 Навигация: Вакансии • Задачи • Собесы
Библиотека питониста
#буст
Forwarded from Вайб-кодинг
This media is not supported in your browser
VIEW IN TELEGRAM
Сохраняем: постоянно обновляемый список на 100% бесплатных API для LLM, которые остаются бесплатными навсегда.
В список входят Google AI Studio, Groq, Cerebras, OpenRouter, NVIDIA NIM, Mistral и десятки других сервисов с точными лимитами запросов и поддержкой OpenAI SDK в одном месте.
Уже 25 тыс. звёзд на GitHub. Просто вставьте любой😎
В список входят Google AI Studio, Groq, Cerebras, OpenRouter, NVIDIA NIM, Mistral и десятки других сервисов с точными лимитами запросов и поддержкой OpenAI SDK в одном месте.
Уже 25 тыс. звёзд на GitHub. Просто вставьте любой
endpoint в Cursor или Claude Code и начинайте разработку Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Прогер
Claude Code может стать дешевле на 90% благодаря этому коду на GitHub
Суть простая: код встраивается между агентом и терминалом и сжимает вывод команд еще до того, как он попадет в контекст. Это помогает экономить до 90% токенов на каждом запуске. Claude Code, Cursor, Copilot и Gemini видят не длинные логи, а только суть. Поэтому расходы заметно снижаются
✅ подписаться ∙ #полезно
Суть простая: код встраивается между агентом и терминалом и сжимает вывод команд еще до того, как он попадет в контекст. Это помогает экономить до 90% токенов на каждом запуске. Claude Code, Cursor, Copilot и Gemini видят не длинные логи, а только суть. Поэтому расходы заметно снижаются
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from [PYTHON:TODAY]
Media is too big
VIEW IN TELEGRAM
Что умеет?
✂️ Не требует разрезать PDF на десятки частей — модель рассчитана на длинные последовательности и может распознавать десятки страниц за один запуск.
Подходит для:
* обучения по электронным книгам;
* оцифровки архивов;
* подготовки данных для RAG;
* поиска информации в больших PDF;
* создания собственных AI-баз знаний.
Клонируем проект:
git clone https://github.com/baidu/Unlimited-OCR
cd Unlimited-OCR
Устанавливаем зависимости:
pip install torch torchvision transformers pymupdf pillow matplotlib einops addict easydict psutil
from transformers import AutoModel, AutoTokenizer
model = AutoModel.from_pretrained(
"baidu/Unlimited-OCR",
trust_remote_code=True
)
Простой пример распознавания PDF:
model.infer_multi(
tokenizer,
prompt='<image>Multi page parsing.',
image_files=pdf_to_images('your_doc.pdf', dpi=300),
output_path='your/output/dir',
image_size=1024,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=1024,
save_results=True,
)
Ключевая особенность — возможность обрабатывать длинные документы целиком без традиционного разбиения на страницы, что упрощает конвейер обработки и ускоряет работу с большими объемами данных.
#python #soft #github
Please open Telegram to view this post
VIEW IN TELEGRAM