本文我們在上篇文章《Flask web開發 處理POST請求(登錄案例)》的基礎上,來講述Flask對session的支持。
在上面案例上,我們需要修改和新增如下功能
1、登錄成功后的 url不再是 http://192.168.142.138/home?username=admin
而是http://192.168.142.138/home
其中在頁面顯示的username信息,由模板代碼從session中獲取
2、當沒有登錄之前,在瀏覽器輸入http://192.168.142.138/xxxx 地址,會跳轉到http://192.168.142.138/login頁面,
當登錄成功后,會進入http://192.168.142.138/xxxx頁面。 其中xxx是已經存在的url。
下面我們來一步步的實現(代碼在上個案例基礎上改進的,這里不再從頭說起):
1、修改run.py文件,修改后的文件內容如下
from flask import Flask from flask import render_template, redirect,url_for from flask import request,session app = Flask(__name__) @app.route('/login', methods=['POST','GET']) def login(): error = None if request.method == 'POST': if request.form['username']=='admin': session['username'] = request.form['username'] return redirect('/home') else: error = 'Invalid username/password' return render_template('login.html', error=error) @app.route('/home') def home(): return render_template('home.html',username=session['username']) app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' if __name__ == '__main__': app.debug = True app.run('0.0.0.0',80)
修改的內容有:
1)登錄成功,將用戶名保留到session中,代碼如session['username'] = request.form['username']
2)登錄成功,重定向到home上,不需要帶username查詢參數
3)home()方法傳入模板的username參數直接從session中使用
4)為了讓session有效,需要設置一個key
注意:上面的代碼有個問題,如果在登錄前,直接在瀏覽器輸入home,是會報錯的,因為這時session中的username還不存在。這個問題我們在下面會解決。
因為加了app.debug=true的設置,run.py修改后,服務自動重啟。這時我們在瀏覽器中重新訪問,發現 登錄成功后的 url不再是 http://192.168.142.138/home?username=admin ,而是http://192.168.142.138/home。 這樣文章開頭說的第一個問題解決了。
下面我們來解決第二個問題。
2、在templates目錄下,增加一個test.html文件,內容可以是隨意一些文字。
我們下面要解決的是,當在登錄之前在瀏覽器輸入 test.html,會跳轉到 login頁面,登錄成功后會自動跳轉到test.html頁面。
3、在run.py中增加一個對test.html的路由,代碼如
@app.route('/test') def test(): return render_template('test.html');
4、修改run.py文件,修改后的內容如下
from flask import Flask from flask import render_template, redirect,url_for from flask import request,session app = Flask(__name__) @app.route('/login', methods=['POST','GET']) def login(): error = None if request.method == 'POST': if request.form['username']=='admin': session['username'] = request.form['username'] if 'newurl' in session: newurl = session['newurl'] session.pop('newurl', None) return redirect(newurl) else: return redirect('/home') else: error = 'Invalid username/password' return render_template('login.html', error=error) @app.route('/home') def home(): return render_template('home.html',username=session['username']) @app.route('/test') def test(): if 'username' in session: return render_template('test.html') else: session['newurl']='test' return redirect(url_for('login')) app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' if __name__ == '__main__': app.debug = True app.run('0.0.0.0',80)
上面的代碼,與前面相比。在test請求的響應處理中,判斷session中是否存在username,不存在就跳轉到login頁面,並把test地址在session中保存。
然后在login的post請求中,檢查newurl是否存在,存在的話表示是由別的頁面跳轉到登錄頁面的,這樣登錄成功后跳轉到相應頁面,缺省是跳轉到home頁面。
這樣我們文章開頭提的第2個問題看上去也解決了。為什么說看上去呢? 因為實際是有問題的。 我們這個是對test請求做了特殊處理。我們應該能對所有的請求(包括還存在問題的home請求)做攔截,判斷是否登錄,如果沒登錄,就跳轉到登錄頁面。
這個問題我們在后續的文章中處理,處理的核心思路是在請求達到每個具體的路由代碼之前,能進行攔截和判斷是否登錄。