在SQLAlchemy中进行过滤时访问关系的backref

时间:2019-05-09 18:01:01

标签: python python-3.x sqlalchemy

我有一个名为 public static void main(String[] args) { MineSweeper ms = new MineSweeper(9,9); int test; // remove code here test = ms.tile[0][0].getNeighbours(); System.out.println("Test: " + test); } public class MineSweeper { Tile tile[][]; MineSweeper(int x,int y) { tile = new Tile[x][y]; // create Tiles here for (int i=0;i<x;i++) for (int j=0;j<y;j++) tile[i][j]=new Tile(); } } 的表,该表与ExtendedUser表具有一对一的关系,在User表上有一个名为extended_user的后向引用。 User表与User表具有一对多关系,在UserPosts表上有一个名为posts的后向引用。

User

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没有帖子的ExtendedUser。 所以我尝试失败的是

User

但这不起作用,我得到一个错误:

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

如何为查询建模,以便仅返回AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with ExtendedUser.user has an attribute 'posts' ExtendedUser个的User个?

1 个答案:

答案 0 :(得分:0)

发生错误是因为.user属性是不同的东西,具体取决于您是从类还是从类的实例访问它。例如,这引发了您得到的异常:

ExtendedUser.user.posts

这是因为访问类.user上的ExtendedUser返回一个InstrumentedAttribute对象,并且InstrumentedAttribute的实例没有名为posts的属性。

这有效:

inst = ExtendedUser()
inst.user.posts

以上方法之所以有效,是因为我们在.user实例上访问了ExtendedUser,该实例返回了User instance 具有名为posts的属性。

类和实例属性访问之间的这种不同行为是由Python的descriptor protocol控制的。

一种实现目标的方法是使用子查询在user_id表中查询唯一的user_posts,并测试ExtendedUser的{​​{1}}不在结果中:

user_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=False。您的示例在User.extended_user上有uselist=False,但是这里不需要,因为在ExtendedUser.user上定义了外键,因此ExtendedUser只能指向一个用户,而sqlalchemy会自动知道该集合不应该是列表。没有该更改,我将得到ExtendedUser.user异常。

好的,这是示例:

TypeError: Incompatible collection type: ExtendedUser is not list-like