FastAPI использующее SQLAlchemy_2.0
                  
                  
                      Есть функция возвращающая Shift c загруженными предварительно связанными Member.user и Member.reports. Которая использует для этого рекомендованный метод selectinload Необходимо изменить её так, чтобы возвращались связанные данные только тех Member, у которых Member.user.is_test_user == False
                  
                  
                  
                  
                  
                  Модели:
                  
                  
                  
                  
                  
                  class Shift(Base):
                  
                  
                      __tablename__ = "shifts"
                  
                  
                      reports = relationship("Report", back_populates="shift")
                  
                  
                      members = relationship("Member", back_populates="shift")
                  
                  
                  
                  
                  
                  class User(Base):
                  
                  
                      __tablename__ = "users"
                  
                  
                      members = relationship("Member", back_populates="user")
                  
                  
                      is_test_user = Column(Boolean, default=False, nullable=False)
                  
                  
                  
                  
                  
                  class Member(Base):
                  
                  
                      __tablename__ = "members"
                  
                  
                      status = Column(String(10))
                  
                  
                      user_id = Column(UUID(as_uuid=True), ForeignKey(User.id), nullable=False)
                  
                  
                      user = relationship("User", back_populates="members")
                  
                  
                      shift_id = Column(UUID(as_uuid=True), ForeignKey(Shift.id), nullable=False)
                  
                  
                      shift = relationship("Shift", back_populates="members")
                  
                  
                      reports = relationship("Report", back_populates="member")
                  
                  
                  
                  
                  
                  class Report(Base):
                  
                  
                      __tablename__ = "reports"
                  
                  
                      shift_id = Column(UUID(as_uuid=True), ForeignKey(Shift.id), nullable=False)
                  
                  
                      shift = relationship("Shift", back_populates="reports")
                  
                  
                      member_id = Column(UUID(as_uuid=True), ForeignKey(Member.id), nullable=False)
                  
                  
                      member = relationship("Member", back_populates="reports")
                  
                  
                  
                  
                  
                  Функция:
                  
                  
                  
                  
                  
                  async def get_with_members(self, id: UUID, member_status: Optional[str]) -> Shift:
                  
                  
                          member_stmt = Shift.members
                  
                  
                          if member_status:
                  
                  
                              member_stmt = member_stmt.and_(Member.user == member_status)
                  
                  
                          statement = (
                  
                  
                              select(Shift)
                  
                  
                              .where(Shift.id == id)
                  
                  
                              .options(selectinload(Shift.members).selectinload(Member.user))
                  
                  
                              .options(selectinload(Shift.members).selectinload(Member.reports))
                  
                  
                              )
                  
                  
                          request = await self._session.execute(statement)
                  
                  
                          return request.scalars().first()
                  
                  
                  
                  
                  
                  Попытки изменить member_stmt == Shift.members.and_(Member.user.is_test_user==False), вызывают исключение: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Member.user has an attribute 'is_test_user'. Возможно необходимо использовать вместо  selectinload() обычный join() совместно contains_eager()  или subqueryload() ?
                  
                  
                
Кол на пастбин или гист, а то много, тут не воспринимается
 Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  https://pastebin.com/px0Pn7JY
Я бы сделал джоином
А не, ты хочешь чтобы при этом запросе в релейшене были отфильтрованы по полю?
 Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  Да необходимо отсечь тех Members у которых есть связь с User, который, в свою очередь имеет поле User.is_test_user == True
Тогда да, джоин и два условия в where
 Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          Eugene
                          Che
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  statement = ( select(Shift) .join(Shift.members) .where(Shift.id == id, User.is_test_user == False) .options(contains_eager(Shift.members)) ) Изменил statement таким образом, теперь раизится greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place.
Обсуждают сегодня