Python 使用Flask SQLAlchemy优化Flask中的ORM查询

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,

我使用Django和Flask编写了相同的项目。整个代码在我的Github帐户上可用。该网站是一个基于小问题答案的测验网站(以CTF格式提供非常简单的问题)。 以下是链接:

我的问题是关于在SQLAlchemy或Flask SQLAlchemy中优化ORM查询

为了更好地理解,我将尽可能地编写表的模式

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的团队。