Python 使用Flask SQLAlchemy优化Flask中的ORM查询
我使用Django和Flask编写了相同的项目。整个代码在我的Github帐户上可用。该网站是一个基于小问题答案的测验网站(以CTF格式提供非常简单的问题)。 以下是链接:Python 使用Flask SQLAlchemy优化Flask中的ORM查询,python,django,flask,flask-sqlalchemy,django-orm,Python,Django,Flask,Flask Sqlalchemy,Django Orm,我使用Django和Flask编写了相同的项目。整个代码在我的Github帐户上可用。该网站是一个基于小问题答案的测验网站(以CTF格式提供非常简单的问题)。 以下是链接: 我的问题是关于在SQLAlchemy或Flask SQLAlchemy中优化ORM查询 为了更好地理解,我将尽可能地编写表的模式 Teams (id, team_name, email, phone, password) Questions (id, name, body, hint, answer, points,
Teams (id, team_name, email, phone, password)
Questions (id, name, body, hint, answer, points, visible)
Submissions (id, team(fk), question(fk), timestamp)
如果您想看到实际的代码,请点击此处:对于Django-,
对于烧瓶- 对于其中两条路线,
/submissions
和/leadboard
,我必须使用ORM编写某些查询。以下是页面的外观:
对于Django,查询看起来相当不错(或者至少我认为是这样:p)
原始SQL查询如下所示:
SELECT "teams_team"."team_name", COALESCE(SUM("questions_question"."points"), 0) AS "score" FROM "teams_team" LEFT OUTER JOIN "questions_submission" ON ("teams_team"."id" = "questions_submission"."team_id") LEFT OUTER JOIN "questions_question" ON ("questions_submission"."question_id" = "questions_question"."id") GROUP BY "teams_team"."team_name" ORDER BY "score" DESC
SELECT "questions_question"."id", "questions_question"."name", COUNT("questions_submission"."id") AS "submissions" FROM "questions_question" LEFT OUTER JOIN "questions_submission" ON ("questions_question"."id" = "questions_submission"."question_id") GROUP BY "questions_question"."id", "questions_question"."name" ORDER BY "questions_question"."id" ASC
对我的问题的介绍太长了
我的问题从这里开始,我似乎无法使用SQLAlchemy ORM编写这个或类似的查询,PyCharm也没有提供适当的代码完成/建议
对于Flask,我的函数如下所示:
def get_team_score(team):
team_submissions = Submission.query.filter_by(team_id=team.id)
score = sum(
submission.question.points
for submission in team_submissions
)
return score
@question_blueprint.route('/submissions')
def submissions():
all_submissions = [
{
'id': q.id,
'name': q.name,
'submissions': Submission.query.filter_by(question_id=q.id).count()
}
for q in Question.get() # fetch all Question rows
]
return render_template('submissions.html', **{
'submissions': all_submissions
})
@question_blueprint.route('/leaderboard')
def leaderboard():
team_scores = [
{
'team_name': team.team_name,
'score': get_team_score(team)
}
for team in Team.query.filter_by()
]
return render_template('leaderboard.html', **{
'team_scores': team_scores
})
查询没有经过优化,我想知道是否有可能编写像django orm这样优雅的查询,而不必编写原始SQL语句。如果可能的话,我想得到一些关于这两条路线的优化查询
呸。您可以像这样更改上面的代码
@question_blueprint.route('/leaderboard')
def leaderboard():
team_scores =\
Team.query.join(
Submission,
).join(
Question,
).with_entities(
Team.team_name,
func.sum(Question.points).label("score")
).all()
return render_template('leaderboard.html', **{
'team_scores': team_scores
})
在下面的代码段中,您加入团队->提交->问题,然后因为您只需要团队名称和基于每次提交的问题的总分,所以您只需要求和
要使用提交查询问题,您可以像我上面添加的那样进行类似的查询,但不需要计算行的总和,只需将其更改为func.sum,您可以像这样更改上面的代码
@question_blueprint.route('/leaderboard')
def leaderboard():
team_scores =\
Team.query.join(
Submission,
).join(
Question,
).with_entities(
Team.team_name,
func.sum(Question.points).label("score")
).all()
return render_template('leaderboard.html', **{
'team_scores': team_scores
})
在下面的代码段中,您加入团队->提交->问题,然后因为您只需要团队名称和基于每次提交的问题的总分,所以您只需要求和
要使用提交查询问题,您可以像我上面添加的那样执行类似的查询,但不需要计算行的总数,所以您只需将其更改为func.sum,在查看了的答案后,我大致了解了如何在SQLAlchemy中运行查询。我不断修改开尔文的答案,以满足我的需要,而这些问题是完全可行的
@question_blueprint.route('/submissions')
def submissions():
all_submissions = Question.query \
.outerjoin(Submission) \
.group_by(Question.id) \
.order_by(Question.id) \
.with_entities(
Question.id,
Question.name,
func.count(Submission.id).label('submissions')) \
.all()
return render_template('submissions.html', **{
'submissions': all_submissions
})
@question_blueprint.route('/leaderboard')
def leaderboard():
team_scores = Team.query \
.outerjoin(Submission) \
.outerjoin(Question) \
.group_by(Team.team_name) \
.with_entities(
Team.team_name,
func.coalesce(func.sum(Question.points), 0).label('score')) \
.with_labels().all()
return render_template('leaderboard.html', **{
'team_scores': team_scores
})
在阅读了他的答案之后,我大致了解了如何在SQLAlchemy中运行查询。我不断修改开尔文的答案,以满足我的需要,而这些问题是完全可行的
@question_blueprint.route('/submissions')
def submissions():
all_submissions = Question.query \
.outerjoin(Submission) \
.group_by(Question.id) \
.order_by(Question.id) \
.with_entities(
Question.id,
Question.name,
func.count(Submission.id).label('submissions')) \
.all()
return render_template('submissions.html', **{
'submissions': all_submissions
})
@question_blueprint.route('/leaderboard')
def leaderboard():
team_scores = Team.query \
.outerjoin(Submission) \
.outerjoin(Question) \
.group_by(Team.team_name) \
.with_entities(
Team.team_name,
func.coalesce(func.sum(Question.points), 0).label('score')) \
.with_labels().all()
return render_template('leaderboard.html', **{
'team_scores': team_scores
})
对于排行榜逻辑,我在加入后使用了group_by,但它不显示得分为0的团队。对于排行榜逻辑,我在加入后使用group_by,但它不显示得分为0的团队。