每个烧瓶视图功能有多个路径是不好的做法吗?

时间:2014-03-14 16:26:24

标签: python flask flask-sqlalchemy flask-wtforms

所以基本上我基于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)

2 个答案:

答案 0 :(得分:7)

这个问题的答案可能与个人品味有关,但我个人不会做这样的事情。我的主要原因只是让事情变得简单 - 你在该函数中有三个嵌套的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。

答案 1 :(得分:1)

没有严格的规则,但我建议拆分成多个函数更符合Separation of concerns原则。

我甚至更进一步使用MethodView,其中每条路线都有一个班级,其中包括从基地覆盖的get,post,post等。

当你的功能很小时它看起来不错,但是当它增长时,某些模块化会有所帮助!