Комментарии 27
class GenderEnum(str, enum.Enum):
Здесь можно не использовать множественное наследование. В стандартной библиотеке Enum есть класс StrEnum, также есть и IntEnum
А если генерировать запросы к postgress, и вызывать эти запросы асинхронно, вместо одного большого запроса, также можно использовать sqlachemy ? Только непонятно, не ту ли ограничения, у postgres на количесто асинхронных вызовов
Эту тему плотно планирую рассмотреть в следующей статье. Что касается ограничений на стороне PostgreSQL - они снимаются достаточно просто. Суть алхимии в том, что при использовании питоновского кода появляется возможность генерировать сложные SQL запросы.
По вызову запосов асинхронно. Тут нужно хорошо разобраться в теме сессий и об этом я подробно расскажу в следующий раз)
Спасибо!!! Достойный материал. Очень доходчево написано.
Спасибо. Отличная статья. Отдельное спасибо за ENUM миграции. В своё время попал в очень неприятную ситуацию из-за незнания этого нюанса на боевом проекте. В связи с чем в дальнейшем стал избегать этого типа в алхимии. Теперь можно попробовать вернуться. Вопрос: нужно изначально указывать create_type=False? С самой первой миграции?
Тс, asyncpg на какой версии питона тут работает? На 3.13 не хочет подтягиваться.
Топовая статья!
Для использования этого параметра с ENUM, нужно передавать значение в виде текстового выражения с помощью метода
text
, который импортируется из SQLAlchemy. Значение ENUM указывается в кавычках как текст, например:"WRITER"
, а не само значение, такое какProfessionEnum.WRITER
. Это необходимо для корректного выполнения запроса на стороне базы данных.
Но ведь можно просто указать ProfessionEnum.WRITER.name
.
В остальном достаточно неплохая статья для новичков.
Во-первых не name, а value. Во-вторых вы не правы. Такая запись как вы предложили вызовет ошибку. Для получения данных нам ничего не будет мешать использовать конструкцию ProfessionEnum.WRITER.value, но в качестве описания ENUM через Mapped такой подход вызовет ошибку.
Или, чтоб не заморачиваться, можно описать Pydantic модель, которая автоматически вернет значение.
class ProfilePydantic(BaseModel):
first_name: str
last_name: str | None
age: int | None
gender: GenderEnum
profession: ProfessionEnum
interests: List[str] | None
contacts: dict | None
class Config:
from_attributes = True
use_enum_values = True
Во-первых, name, а не value, потому что name вернёт "WRITER"
(именно строку), когда как value вернёт "писатель"
. Во-вторых, не будет никакой ошибки, так как по сути ничего не меняется — вы просто более явно передаёте параметр. Вы бы хоть попробовали, прежде чем минус мне лепить.
Не понял, какое имеет отношение ваш пример со схемой Pydantic к server_default
, но вместо Config
сейчас используется параметр model_config
с ConfigDict
.
Я не понимаю почему мой метод ошибочен? Востановил баланс несправедливой оценки. Неправильно вас понял)
Мне тут предстоит на fastapi API к mysql писать (БД для работающего недоCRM, поменять нельзя). Насколько безопасно инфу из статей с asyncmy использовать не подскажите? Или ждет увлекательное хождения по граблям?
Классная статья, также по работе с enum можно было рассказать про параметр native_enum, который при отключении будет преобразовывать объекты enum на стороне алхимии, а в базе просто хранить str значение, тогда при добавлении/удалении нового объекта в enum не придется думать, что нужно в миграции дописать руками обновление enum таблицы
building_type: Mapped[HouseTypeEnum] = mapped_column( # noqa: F821
Enum(HouseTypeEnum, native_enum=False, length=255),
)
Для новичка отлично, спасибо! Хотелось бы разобрать вопрос с созданием таблицы группы, подгруппы, когда запись в таблице ссылается на запись в этой же таблице. Как ее создавать, как тянуть из нее данные, как писать сериализатор для FastAPI.
А меня одного смущает пропажа полей названия таблицы и id, для кода в конце?
Тут есть
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) name: Mapped[str]
А тут уже нету:
class User(Base):
username: Mapped[uniq_str_an]
email: Mapped[uniq_str_an]
password: Mapped[str]
profile_id: Mapped[int | None] = mapped_column(ForeignKey('profiles.id'))
Это баг или фича?
Я думаю, что если бы вы внимательно читали, то у вас бы не было вопросов) Мы такие поля как id, created_at и updatet_at, как и название таблиц, уже закрыли в базовом классе Base. Для этого мы прописали следующее:
class Base(AsyncAttrs, DeclarativeBase):
__abstract__ = True # Класс абстрактный, чтобы не создавать отдельную таблицу для него
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
created_at: Mapped[datetime] = mapped_column(server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(server_default=func.now(), onupdate=func.now())
@declared_attr.directive
def __tablename__(cls) -> str:
return cls.__name__.lower() + 's'
Спасибо, чётко и по делу
from database import Base, uniq_str_an, array_or_none_an, content_an
Нигде не нашел реализацию алиаса -> content_an.
напишите его пожалуйста, или подскажите где посмотреть.
Асинхронный SQLAlchemy 2: простой пошаговый гайд по настройке, моделям, связям и миграциям с использованием Alembic