The answer to this question is probably a little bit down to personal taste, but personally I'd avoid doing things like this. My main reason would just be to keep things simple - you've got three nested if statements inside that function, that are basically doing the exact same job as flasks routing logic would do if you were to split up the views.
Admittedly it's not a massive problem at present, but if you were to add more logic in to any of the paths then it could lead to a surprisingly complex function. This could lead to subtle bugs, or just plain difficulty understanding exactly what's going on from a glance.
If you split things up however, it should be obvious at a glance exactly what each route is doing. Doesn't even involve more code, since you can cut out on all the if statements:
@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)
EDIT: To clarify - I'm not saying it's wrong to have more than one url per flask route. In this case I think it's a bad idea to have a single function doing three fairly different things. There are other use cases for multiple routes per view that I do make use of. For example, in my own code I frequently have views like this:
@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
Where the alternative route accepts a cursor into a database query for pagination. The flow of the code is basically the same, it just has different URLs for the first page and subsequent pages.