#python #sqlalchemy
#питон #sqlalchemy
Вопрос:
Недавно я исправлял некоторые ошибки, связанные с разбиением на страницы. Это произошло из-за обратного соединения, и из-за этого появились целевые строки. Подобный этому:
class User(Base): __tablename__ = "users" id = sa.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) email = Column(String, index=True, nullable=False, unique=True) class UserPermission(Base): __tablename__ = "users_permissions" id = sa.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) user_id = Column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False ) permission = Column(String, nullable=False, index=True) __table_args__ = (UniqueConstraint("user_id", "permission"),) # results = db.execute( # select(User).join(UserPermission).where(UserPermission.permission.in_( # ["can_access_first_thing", "can_access_second_thing"] # ) # ).unique().scalars().all()
Иногда запрос, выполняемый для заполнения results
, будет содержать больше строк, чем существующих Users
, потому что для каждого пользователя их будет несколько UserPermission
. Это нарушает любую разбивку на страницы, основанную на offset
/ limit
подходе. Мое решение этой проблемы с разбиением на страницы состояло в том, чтобы users
снова запросить таблицу после определения всех необходимых идентификаторов пользователей:
base_query = select(User).join(UserPermission).where(UserPermission.permission.in_( ["can_access_first_thing", "can_access_second_thing"] ).with_only_columns(User.id) results = db.execute(select(User).where(User.id.in_(base_query.subquery())))
Теперь SQLAlchemy выдает предупреждение для этой строки: SAWarning: Coercing Subquery object into a select() for use in IN(); please pass a select() construct explicitly
. Мой вопрос в том, как правильно переписать существующий запрос, чтобы он возвращал тот же результат, не выдавая этого предупреждения.