python - 如何在 Flask-SQLAlchemy 中按用户获取不同列条目的数量?
问题描述
我有一个用户活动数据库。对于特定用户,我想返回他们所做的不同类型活动的数量。例如:
Bob:
活动 1:A 型
活动 2:B 型
活动 3:A 型
结果应该是 2,因为有两个不同的活动(A 和 B)。
我尝试了以下命令:
Activity.activity_type.query.filter(Activity.user_id==1).distinct(Activity.activity_type)
该Activity.activity_type
部分给出错误。我查看了 StackOverflow 和文档,但找不到distinct
在这种情况下如何正确使用。我将不胜感激有关如何使此查询正常工作的帮助。
解决方案
请原谅我对您的目标的原始解释,它不正确,因为返回了每个尝试的活动的计数,而不是尝试的不同活动的计数。
有关 Ilja Everilä 在评论中提供的问题的解决方案,请参见下文。
但是,您遇到的异常发生在您的查询执行之前(我认为,因为我已经从您提供的查询中对您的模型进行了逆向工程)所以这个答案的大部分集中在:
AttributeError:与 Activity.activity_type 关联的“InstrumentedAttribute”对象和“比较器”对象都没有属性“查询”
我创建了这些模型以执行您的查询:
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
的一个实例,但是却显示了,所以这是错误中引用的第一个对象。这是一个内部 sqlalchemy 构造,它也被检查(如果你有兴趣,你可以找到它)。因此 sqlalchemy 查找并找不到列上具有名称的属性。Column
print(Activity.activity_type)
<class 'sqlalchemy.orm.attributes.InstrumentedAttribute'>
Comparitor
Activity.activity_type.comparator
'query'
Activity.activity_type
该.query
属性来自db.Model
您的模型继承的基础,并且仅可用于与db.Model
. 由于列对象不继承自db.Model
,因此您无法通过它们访问查询属性。Activity.query
是合法的,Activity.activity_type.query
不是。
这是 Ilja 在对我的原始答案的评论中提供的查询,这是正确的解决方案:
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.
推荐阅读
- c# - 实体框架 DbContext 和延迟加载
- javascript - 加载并显示有条件的数据,但不满足条件
- c# - 如何使用 AutoMapper 中的自定义逻辑从其他属性映射属性?
- android - 如何在材质按钮的一侧添加边框颜色?
- python - Airflow KubernetesExecutor 调度程序 kube watch 进程死亡
- angular - 如何在 Ionic 4 中使用 Firebase 处理刷新令牌?
- e2e-testing - 赛普拉斯测试项目清单。没有收到任何物品时出错?
- javascript - 如何在 sweetalert 中采取两个选项并根据该选项采取行动?
- c++ - 如何使用 C++ 进行矩阵行和列命名?
- python - 两个列表给出相同值的列表的逻辑错误