Python 在SQLAlchemy中筛选时访问关系上的backref
我有一个名为Python 在SQLAlchemy中筛选时访问关系上的backref,python,python-3.x,sqlalchemy,Python,Python 3.x,Sqlalchemy,我有一个名为ExtendedUser的表,它与User表有一对一的关系,在User表上有一个名为extended\u User的backref。User表与UserPosts表有一对多关系,在User表上有一个名为posts的backref 类用户(基本): __tablename_=“用户” id=列(整数,主键=True) 类UserPost(基): __tablename=“user\u posts” id=列(整数,主键=True) user\u id=列(整数,ForeignKey(“
ExtendedUser
的表,它与User
表有一对一的关系,在User
表上有一个名为extended\u User
的backref。User
表与UserPosts
表有一对多关系,在User
表上有一个名为posts
的backref
类用户(基本):
__tablename_=“用户”
id=列(整数,主键=True)
类UserPost(基):
__tablename=“user\u posts”
id=列(整数,主键=True)
user\u id=列(整数,ForeignKey(“users.id”))
用户=关系(“用户”,backref=“posts”)
类延伸器(基本):
__tablename=“扩展用户”
user\u id=Column(整数,ForeignKey(“users.id”),primary\u key=True)
用户=关系(“用户”,backref=“扩展用户”,uselist=False,lazy=“已加入”)
从extendeducer
开始,我想选择extendeducer
s中User
s没有post的所有extendeducer
s。
所以我尝试做的失败是
sess.query(ExtendedUser.filter)(而不是(ExtendedUser.user.posts.any())
但这不起作用,我得到一个错误:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with ExtendedUser.user has an attribute 'posts'
如何对查询进行建模,以便仅返回其
User
具有UserPost
s的ExtendedUser
s?发生错误的原因是.User
属性是不同的,这取决于您是从类还是从类的实例访问它。例如,这会引发您正在获得的异常:
ExtendedUser.user.posts
这是因为访问类扩展程序上的.user
会返回一个InstrumentedAttribute
对象,并且InstrumentedAttribute
的实例没有名为posts
的属性
这项工作:
inst=ExtendedUser()
仪器用户职位
上述方法之所以有效,是因为我们访问了.user
的一个ExtendedUser
实例,该实例返回一个名为posts
的user
实例
类和实例属性访问之间的这种不同行为由Python的
实现目标的一种方法是使用子查询在user\u posts
表中查询唯一的user\u id
s,并测试extender
的user\u id
不在结果中:
q = sess.query(ExtendedUser).\
filter(
not_(
ExtendedUser.user_id.in_(
sess.query(UserPost.user_id).distinct()
)
)
)
下面是一个工作示例,但首先我必须稍微更改ExtendedUser.user
的定义:
类扩展控制器(基本):
...
用户=关系(
“用户”,backref=backref(“扩展用户”,uselist=False),lazy=“已加入”)
注意使用了backref
功能,该功能允许我在User.extended\u User
上设置uselist=False
。您的示例在ExtendedUser.user
上有uselist=False
,但不需要它,因为外键是在ExtendedUser
上定义的,因此ExtendedUser.user
只能指向一个用户,sqlalchemy将自动知道集合不应该是列表。如果没有这个更改,我将得到一个TypeError:compatible collection type:ExtendedUser不是类似列表的异常
好的,下面是一个例子:
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)]
谢谢,这是一个很好的解决方案。我使用的方法来自我的实体框架背景,在那里类似的表达式可以无缝工作。我现在意识到SQLAlchemy可能更接近纯SQL(较低级别),这意味着它没有那么神奇,但生成的查询可能更简单。我不能给你投票,因为我的代表率低,如果可以的话,我会给你投票。对不起,不用担心,很乐意帮忙。很可能还有其他的解决方案,我觉得这只是一个直截了当的解决方案。祝你一切顺利。