你可以通过
request.cookies字典访问请求cookie,并通过使用
make_response或仅将调用结果存储
render_template在变量中然后调用
set_cookie响应对象来设置cookie :
@app.route("/")def home(): user_id = request.cookies.get('YourSessioncookie') if user_id: user = database.get(user_id) if user: # Success! return render_template('welcome.html', user=user) else: return redirect(url_for('login')) else: return redirect(url_for('login'))@app.route("/login", methods=["GET", "POST"])def login(): if request.method == "POST": # You should really validate that these fields # are provided, rather than displaying an ugly # error message, but for the sake of a simple # example we'll just assume they are provided user_name = request.form["name"] password = request.form["password"] user = db.find_by_name_and_password(user_name, password) if not user: # Again, throwing an error is not a user-friendly # way of handling this, but this is just an example raise ValueError("Invalid username or password supplied") # Note we don't *return* the response immediately response = redirect(url_for("do_that")) response.set_cookie('YourSessioncookie', user.id) return response@app.route("/do-that")def do_that(): user_id = request.cookies.get('YourSessioncookie') if user_id: user = database.get(user_id) if user: # Success! return render_template('do_that.html', user=user) else: return redirect(url_for('login')) else: return redirect(url_for('login'))DRYing up the pre
现在,你会注意到和方法中有很多样板,所有这些都与登录有关。你可以通过编写自己的装饰器来避免这种情况(如果你想了解更多关于装饰器的信息,请参阅什么是装饰器):homedo_that
from functools import wrapsfrom flask import flashdef login_required(function_to_protect): @wraps(function_to_protect) def wrapper(*args, **kwargs): user_id = request.cookies.get('YourSessioncookie') if user_id: user = database.get(user_id) if user: # Success! return function_to_protect(*args, **kwargs) else: flash("Session exists, but user does not exist (anymore)") return redirect(url_for('login')) else: flash("Please log in") return redirect(url_for('login')) return wrapper然后,你的home和do_that方法变得更短:
# Note that login_required needs to come before app.route# Because decorators are applied from closest to furthest# and we don't want to route and then check login status@app.route("/")@login_requireddef home(): # For bonus points we *could* store the user # in a thread-local so we don't have to hit # the database again (and we get rid of *this* boilerplate too). user = database.get(request.cookies['YourSessioncookie']) return render_template('welcome.html', user=user)@app.route("/do-that")@login_requireddef do_that(): user = database.get(request.cookies['YourSessioncookie']) return render_template('welcome.html', user=user)Using what’s provided
如果你不需要 cookie来使用特定的名称,我建议你使用flask.session它,因为它已经内置了很多功能(它已签名,因此不能被篡改,可以设置为仅HTTP,等等)。 )。这会使我们的
login_required装饰器更加干燥:
# You have to set the secret key for sessions to work# Make sure you keep this secretapp.secret_key = 'something simple for now' from flask import flash, sessiondef login_required(function_to_protect): @wraps(function_to_protect) def wrapper(*args, **kwargs): user_id = session.get('user_id') if user_id: user = database.get(user_id) if user: # Success! return function_to_protect(*args, **kwargs) else: flash("Session exists, but user does not exist (anymore)") return redirect(url_for('login')) else: flash("Please log in") return redirect(url_for('login'))然后,你的各个方法可以通过以下方式吸引用户:
user = database.get(session['user_id'])



