我有一个用户活动数据库。对于特定用户,我想返回他们执行的不同类型的活动的数量。例如:
鲍勃:
活动1:A型
活动2:B型
活动3:类型
由于两个不同的活动(A和B),结果应该为2。
我尝试了以下命令:
Activity.activity_type.query.filter(Activity.user_id==1).distinct(Activity.activity_type)
Activity.activity_type
部分出现错误。我查看了StackOverflow和文档,但是在这种情况下找不到正确使用distinct
的方法。我希望能获得有关如何使此查询正常工作的帮助。
答案 0 :(得分:1)
请原谅我对您的目标的解释,这是不正确的,因为返回的是每次尝试的活动的计数,而不是对尝试的不同活动的计数。
IljaEverilä在评论中提供的问题的解决方法,请参见下文。
但是,您遇到的异常发生在执行查询之前(我认为,因为我已经根据所提供的查询对模型进行了反向工程),因此,此答案的大部分重点在于:< / p>
AttributeError:既不是'InstrumentedAttribute'对象,也不是 与Activity.activity_type关联的“比较器”对象具有一个 属性“查询”
我创建这些模型是为了执行您的查询:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16))
class Activity(db.Model):
activity_id = db.Column(db.Integer, primary_key=True)
activity_type = db.Column(db.String(32))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User')
然后写了一个小脚本来添加一些数据:
if __name__ == '__main__':
with app.app_context():
db.drop_all()
db.create_all()
names = ['batman', 'a', 'list', 'of', 'names']
users = [User(name=name) for name in names]
db.session.add_all(users)
activities = [
'Self Doubt',
'Dark Introspection',
'Gotham Needs Me',
'Training Montage',
'Fight Crime',
'Get the girl'
]
db.session.add_all(
[Activity(
activity_type=random.choice(activities),
user=random.choice(users)
) for _ in range(20)]
)
db.session.commit()
执行Activity.activity_type.query.filter(Activity.user_id==1).distinct(Activity.activity_type)
会产生上述错误。
问题来自查询Activity.activity_type.query
的这一部分。就是说,它在'query'
上查找了名为Activity.activity_type
的属性,但找不到它。细分错误消息:
当我们在模型上定义Activity.activity_type
时,我们知道Column
是print(Activity.activity_type)
的实例,但是<class 'sqlalchemy.orm.attributes.InstrumentedAttribute'>
显示了Comparitor
,因此这是错误中引用的第一个对象。 Activity.activity_type.comparator
是一个内部sqlalchemy构造,也已对其进行检查(如果您有兴趣,可以使用'query'
找到它)。因此sqlalchemy在Activity.activity_type
列上查找但找不到名称为.query
的属性。
db.Model
属性来自模型继承的db.Model
基,并且仅与db.Model
处于同一MRO中的对象可用。由于列对象不是从Activity.query
继承的,因此您无法通过它们访问查询属性。 Activity.activity_type.query
是合法的, batman_activity_count = db.session.query(
db.func.count(
Activity.activity_type.distinct()
)
).filter(Activity.user_id==1).scalar()
print(batman_activity_count) # random integer b/w 0 and 6.
不是合法的。
这是Ilja在对我的原始答案的评论中提供的查询,这是正确的解决方案:
{{1}}