簡體   English   中英

在SQLAlchemy中進行過濾時訪問關系的backref

[英]Access backref on relationship when filtering in SQLAlchemy

我有一個名為表ExtendedUser ,有一個人跟一個關系User與名為backref表extended_userUser表。 User表有一個與許多關系UserPosts表與backref命名postsUser表。

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)

class UserPost(Base):
    __tablename__ = "user_posts"

    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey("users.id"))
    user = relationship("User", backref="posts")

class ExtendedUser(Base):
    __tablename__ = "extended_users"

    user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
    user = relationship("User", backref="extended_user", uselist=False, lazy="joined")

ExtendedUser開始,我想選擇所有User沒有帖子的ExtendedUser 所以我嘗試失敗的是

sess.query(ExtendedUser).filter(not_(ExtendedUser.user.posts.any()))

但這不起作用,我得到一個錯誤:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with ExtendedUser.user has an attribute 'posts'

如何為查詢建模,以便僅返回User擁有UserPostExtendedUser

發生錯誤是因為.user屬性是不同的東西,具體取決於您是從類還是從類的實例訪問它。 例如,這引發了您得到的異常:

ExtendedUser.user.posts

這是因為在類ExtendedUser上訪問.user返回InstrumentedAttribute對象,而InstrumentedAttribute實例沒有名為posts屬性。

這有效:

inst = ExtendedUser()
inst.user.posts

上面的方法起作用是因為我們已經在ExtendedUser 實例上訪問了.user ,該實例返回了User 實例 ,該實例具有名為posts的屬性。

類和實例屬性訪問之間的這種不同行為是由Python的描述符協議控制的。

實現目標的一種方法是使用子查詢在user_posts表中查詢唯一的user_id ,並測試結果中是否沒有ExtendedUseruser_id

q = sess.query(ExtendedUser).\
    filter(
        not_(
            ExtendedUser.user_id.in_(
                sess.query(UserPost.user_id).distinct()
            )
        )
    )

以下是一個有效的示例,但首先我必須稍微更改ExtendedUser.user的定義:

class ExtendedUser(Base):
    ...
    user = relationship(
        "User", backref=backref("extended_user", uselist=False), lazy="joined")

注意使用的backref功能,讓我設置uselist=FalseUser.extended_user 您的示例在ExtendedUser.user上具有uselist=False ,但是在那里不需要,因為在ExtendedUser上定義了外鍵,因此ExtendedUser.user只能指向一個用戶,並且sqlalchemy會自動知道該集合不應為一個列表。 沒有該更改,我將得到TypeError: Incompatible collection type: ExtendedUser is not list-like異常。

好的,這是示例:

sess = Session()
user_1 = User(extended_user=ExtendedUser())
user_2 = User(extended_user=ExtendedUser())
user_3 = User(extended_user=ExtendedUser())
user_1.posts = [UserPost()]
sess.add_all([user_1, user_2, user_3])
sess.commit()
q = sess.query(ExtendedUser).\
    filter(
        not_(
            ExtendedUser.user_id.in_(
                sess.query(UserPost.user_id).distinct()
            )
        )
    )

print(q.all())  # [ExtendedUser(user_id=2), ExtendedUser(user_id=3)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM