Ответ
В SQLAlchemy модуль typing используется для статической типизации, что значительно улучшает работу с IDE (автодополнение, подсветка ошибок) и позволяет проводить проверку кода с помощью инструментов вроде mypy.
Основное применение — аннотация моделей и типов возвращаемых значений из запросов.
SQLAlchemy 2.0+ (рекомендуемый подход)
В современных версиях SQLAlchemy используется декларативный стиль с аннотациями типов. Для связи между атрибутом Python и колонкой в БД используются Mapped и mapped_column.
from typing import List, Optional
from sqlalchemy import create_engine, String
from sqlalchemy.orm import Mapped, mapped_column, Session, declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
# Аннотации типов для колонок
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
age: Mapped[Optional[int]] # Для nullable-полей используется Optional
# Аннотация типов в функциях
def get_all_users(session: Session) -> List[User]:
"""Функция возвращает список объектов User."""
return session.query(User).all()
def get_user_by_id(session: Session, user_id: int) -> Optional[User]:
"""Функция возвращает один объект User или None."""
return session.query(User).get(user_id)
Ключевые моменты:
Mapped[<python_type>]: Указывает, что атрибут класса сопоставлен с колонкой в базе данных.Optional[<python_type>]: Используется для колонок, которые могут иметь значениеNULL(nullable=True).List[<Model>]: Применяется для аннотации результатов, возвращающих несколько записей (например, после.all()).
Ответ 18+ 🔞
А, ну это же про типизацию в SQLAlchemy, блядь! Ну, слушай, тут всё просто, как три копейки, только с припиздью.
Вот смотри, в SQLAlchemy модуль typing — это типа такой костыль для твоего IDE, чтобы он не тупил, как мартышлюшка, и понимал, что ты вообще делаешь. Автодополнение летит, ошибки подсвечивает — красота, ёпта! А ещё mypy этим пользуется, чтобы тебе мозги не выносить раньше времени.
SQLAlchemy 2.0+ (нормальный, современный подход)
Сейчас всё делают через декларативку и эти ваши аннотации. Чтобы связать питонячье поле с колонкой в базе, юзают Mapped и mapped_column. Не путай, а то будет пиздец.
from typing import List, Optional
from sqlalchemy import create_engine, String
from sqlalchemy.orm import Mapped, mapped_column, Session, declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
# Вот тут вся магия типизации и происходит
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
age: Mapped[Optional[int]] # А это для полей, где может быть NULL, понимаешь?
# И в функциях тоже аннотируем, чтобы не было сюрпризов
def get_all_users(session: Session) -> List[User]:
"""Функция возвращает список объектов User."""
return session.query(User).all()
def get_user_by_id(session: Session, user_id: int) -> Optional[User]:
"""Функция возвращает один объект User или None."""
return session.query(User).get(user_id)
Что тут важно, блядь:
Mapped[<python_type>]: Это типа приказ: «Эй, это поле мапится на колонку в базе, запомни!».Optional[<python_type>]: Это для тех самых полей, где может бытьNULL. Без этогоmypyначнёт орать, как сука.List[<Model>]: Когда функция возвращает кучу записей, например, после.all(). Так и пишем — список юзеров, а не просто хуй с горы.
Вот и вся философия. Сделаешь по-старому, без типов — сам себя наебешь потом, когда проект разрастётся до овердохуища строк.