【问题标题】:Is it bad practice to have multiple routes per flask view function?每个烧瓶视图功能有多个路线是不好的做法吗?
【发布时间】:2014-04-20 01:53:04
【问题描述】:

所以基本上我有多个基于 if 语句的 render_template 返回,它们返回我的 jinja2 模板响应的不同变量。我相信我可以将这些路由分解为它们自己的函数(同样,我也可以将我的模板分解为多个模板(例如,一个 edit.html 模板而不是我的模板中的 {% if editform %})),但我喜欢为任何给定页面提供单一视图功能和模板的想法。

在我花更多时间创建其余的视图函数之前,我想确保我正在做的事情以后不会对我不利。

代码如下,谢谢!

@app.route('/admin/users/', defaults={'id': None}, methods = ['GET'])
@app.route('/admin/users/<id>', methods = ['GET'])
@app.route('/admin/users/edit/<id>', methods = ['GET', 'POST'])
@login_required
def users(id):
    if not current_user.role == ROLE_ADMIN:
        flash('You do not have access to view this page.')
        return redirect(url_for('index'))

    if id:
        user = User.query.filter_by(id = id).first()

        if 'edit' in request.path:
            editform = UserForm()

            if editform.validate_on_submit():
                user.username = editform.username.data
                user.email = editform.email.data
                user.role = editform.role.data

                db.session.add(user)
                db.session.commit()

                return redirect('/admin/users/' + str(user.id))

            editform.username.data = user.username
            editform.email.data = user.email
            editform.role.data = user.role

            return render_template("users.html",
                title = "Edit User",
                user = user,
                editform = editform)

        return render_template("users.html",
            title = "User",
            user = user)

    users = User.query.all()

    return render_template("users.html",
        title = 'Users',
        users = users)

【问题讨论】:

  • Flask 应用程序应尽可能模块化,以便尽可能轻松地重复使用或扩展它们。你做事的方式会起作用,但考虑使用blueprints。一般来说,如果我在烧瓶视图中进入第三级条件,我预计它会在以后伤害我。
  • 您可以使用多个 URL,但这不是您想要的方式。那是许多不同的动作。如果它对多个嵌套项执行相同的操作,那么是的,您可以使用多个。如下所述,简单是关键,即使这意味着多条路线
  • @SteveRossiter 感谢您对蓝图的提醒。在这一点上,这些东西有点让我头疼,但现在我知道它存在。

标签: python flask flask-sqlalchemy flask-wtforms


【解决方案1】:

这个问题的答案可能有点取决于个人喜好,但我个人会避免做这样的事情。我的主要原因只是为了保持简单——你在该函数中有三个嵌套的 if 语句,它们的工作基本上与烧瓶路由逻辑在拆分视图时所做的完全相同。

诚然,目前这不是一个大问题,但如果您要在任何路径中添加更多逻辑,那么它可能会导致一个令人惊讶的复杂功能。这可能会导致细微的错误,或者只是难以一目了然地理解到底发生了什么。

但是,如果您将它们分开,那么每条路线的确切用途应该一目了然。甚至不涉及更多代码,因为您可以删除所有 if 语句:

@app.route('/admin/users/', methods = ['GET'])
def get_all_users():
    users = User.query.all()

    return render_template("users.html",
        title = 'Users',
        users = users)

@app.route('/admin/users/<id>', methods = ['GET'])
def get_single_user(id):
    user = User.query.filter_by(id = id).first()

    return render_template("users.html",
        title = "User",
        user = user)

@app.route('/admin/users/edit/<id>', methods = ['GET', 'POST'])
def edit_user(id):
    editform = UserForm()

    if editform.validate_on_submit():
        user.username = editform.username.data
        user.email = editform.email.data
        user.role = editform.role.data

        db.session.add(user)
        db.session.commit()

        return redirect('/admin/users/' + str(user.id))

    editform.username.data = user.username
    editform.email.data = user.email
    editform.role.data = user.role

    return render_template("users.html",
        title = "Edit User",
        user = user,
        editform = editform)

编辑:澄清一下-我并不是说每个烧瓶路线有多个网址是错误的。在这种情况下,我认为让一个函数做三个完全不同的事情是个坏主意。我确实使用了每个视图的多个路由的其他用例。例如,在我自己的代码中,我经常有这样的视图:

@migrations_tasks.route('/external_applications', methods=['GET'])
@migrations_tasks.route('/external_applications/<cursor>', methods=['POST'])
def migrate_external_applications(cursor=None, subdomain=None):
    ... do stuff

替代路由接受一个游标进入数据库查询以进行分页。代码的流程基本相同,只是首页和后续页面的 URL 不同。

【讨论】:

  • 我觉得这是一个更好的解决方案,感谢您的确认!
  • 感谢您的澄清。与@SonyKadavan 关于关注点分离的说法一致。
  • 是否可以存在没有任何路由的视图函数,这些视图函数可以从其他视图函数中调用以实现模块化?
  • @Shafaq 是的,当然。如果它们没有与它们关联的任何路由,我可能只会称它们为“函数”,但那只是我。
【解决方案2】:

没有硬性规定,但我建议按照Separation of concerns 原则拆分成多个功能更加模块化。

我什至会更进一步并使用MethodView,其中每个路由都有一个类,其中 get、post、post 等从 base 覆盖。

当你的函数很小时,它看起来还可以,但当它增长时,一些模块化会有所帮助!

【讨论】:

  • 感谢您的建议。我对 Flask 还是很陌生,而且 MethodView 的东西有点令人困惑,但现在我知道它存在并且可能会在以后感觉更冒险时尝试实现它。
猜你喜欢
  • 2021-08-19
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
相关资源
最近更新 更多