@http80

Как составить такой запрос к БД, используя SQLAlchemy?

Есть две модели SQLAlchemy:

class User(Base):
    __tablename__ = 'user'
    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, index=True)
    username: Mapped[str] = mapped_column(String(32), unique=True, index=True)

    sanctions: Mapped[list['UserSanction']] = relationship(
        'UserSanction', back_populates='user', foreign_keys='[UserSanction.user_id]')
    applied_sanctions: Mapped[list['UserSanction']] = relationship(
        'UserSanction', back_populates='moder', foreign_keys='[UserSanction.moder_id]')

class UserSanction(Base):
    __tablename__ = 'user_sanction'
    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, index=True)
    user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey(User.id))
    moder_id: Mapped[int] = mapped_column(BigInteger, ForeignKey(User.id))
    reason: Mapped[Optional[str]] = mapped_column(String(64))
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)

    user: Mapped[User] = relationship(back_populates='sanctions', cascade='all,delete', foreign_keys=[user_id])
    moder: Mapped[User] = relationship(back_populates='applied_sanctions', foreign_keys=[moder_id])


Нужно каким-то образом получить пользователя по юзернейму, да так, чтобы на выходе был объект User с полем User.sanctions: list[UserSanction] (санкции отфильтрованы по полю is_active - должно быть True), в каждой санкции чтобы также присутствовало ещё и поле moder, являющееся объектом класса User. Представлю желаемый результат в JSON, чтобы было понятнее:

{
  "id": 1,
  "username": "user1",

  "sanctions": [
    {
      "id": 1,
      "moder": {
        "id": 2,
        "username": "Moderator228"
      },
      "reason": "...",
      "is_active": true
    },
    {
      "id": 2,
      "moder": {
        "id": 3,
        "username": "MisterAdmin"
      },
      "reason": "...",
      "is_active": true
    },
  ]
}


Возможно ли это выполнить одним запросом к базе? И, если да, то как это сделать через ORM?

UPD:
Вот такой запрос получилось составить (PostgreSQL), который выполняет все условия, однако как это перенести в ORM?

WITH desired_user AS (
    SELECT id
    FROM "user"
    WHERE username = '________'
)

SELECT u.id AS user_id, u.username,
       s.id AS sanction_id, s.user_id AS sanction_user_id, s.moder_id AS sanction_moder_id, s.is_active AS sanction_is_active,
       m.id AS moder_id, m.username AS moder_username
FROM desired_user du
JOIN "user_sanction" s ON du.id = s.user_id AND s.is_active = true
LEFT JOIN "user" u ON du.id = u.id
LEFT JOIN "user" m ON s.moder_id = m.id;
  • Вопрос задан
  • 79 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы