網站首頁 編程語言 正文
1 使用Flask處理表單
什么是表單(Form)? 表單是搜集用戶數據信息的各種表單元素的集合區域。它的作用是實現用戶和服務器的數據交互。通過表單搜集客戶端輸入的數據信息,如何提交到網站服務器進行處理(搜集錄入/比對驗證等)。Form表單是Web應用中最繼承的一部分。為了能處理Form表單,Flask-WTF擴展提供了良好的支持。
1.1 使用Flask處理通用表單
Flask請求對象包括客戶端發出的所有請求信息,其中,request.form能獲取POST請求中提交的表單數據。盡管Flask的請求對象提供的信息足夠用于處理Web表單,但有些任務很單調,而且需要重復操作。
indexhtml
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <style> .div1 { height: 180px; width: 380px; border: 1px solid #8A8989; margin: 0 auto; } .input { display: block; width: 350px; height: 40px; margin: 10px auto; } .button { background: #2066C5; color: white; font-size: 18px; font-weight: bold; height: 50px; border-radius: 4px; } </style> <div class="div1"> {# action:接受的路由 #} <form action="/login" method="post"> <input type="text" class="input" name="username" placeholder="請輸入用戶名"> <input type="password" class="input" name="pwd" placeholder="請輸入密碼"> <input type="submit" value="登錄" class="input button"> </form> </div> </body> </html>
app.py
# @time:2020/11/8 16:18 # Author:Small-J from flask import Flask, render_template, request app = Flask(__name__) @app.route('/') def hello_world(): return render_template('index5.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': return '這是get請求' else: return '這是post請求' if __name__ == '__main__': app.run(debug=True)
發送post請求成功
使用Postman發送Get請求成功
在上面的工程中,對表單沒有進行必要的保護措施,很容易被人利用,控制用戶在當前已登錄的Web應用程序上執行非本意的操作。因此,在實際部署服務器上的代碼時,不建議使用這個方式處理表單,推薦使用Flask-WTF方式進行表單處理。
1.2 使用Flask-WTF處理表單
Flask-WTF的安裝:pip install flask-wtf
啟動CSRF保護
Flask-WTF
提供了對所有Form表單免受跨站請求偽造(Cross-Site Request Forgery, CSRF)攻擊的技術支持(通過添加動態token令牌的方式)
我們在Flask根目錄下新增config.py
配置文件,要啟動CSRF保護,可以在config.py
中定義兩個變量
# @time:2020/11/8 16:54 # Author:Small-J import os import random # 開啟CSRF保護 CSRF_ENABLED = True # 生成密鑰 SECRET_KEY = os.urandom(24)
form.py
# @time:2020/11/8 17:00 # Author:Small-J # 引入Form元素的基類 from flask_wtf import Form # 引入Form元素的父類 from wtforms import StringField, PasswordField # 引入Form驗證父類 from wtforms.validators import DataRequired, Length # 登錄表單類,繼承于Form類 class BaseLogin(Form): # 用戶名 name = StringField('name', validators=[DataRequired(message="用戶名不能為空"), Length(6, 16, message="長度為6~16之間")], render_kw={'placeholder': '輸入用戶名'}) # 密碼 password = PasswordField('password', validators=[DataRequired(message="密碼不能為空"), Length(6, 16, message='長度位于6~16之間')], render_kw={'placeholder': '輸入密碼'})
app.py
# @time:2020/11/8 16:54 # Author:Small-J from flask import Flask, flash from flask import url_for, render_template from flask_wtf.csrf import CSRFProtect # 導入定義的BaseLogin from forms import BaseLogin import config app = Flask(__name__) # 配置文件初始化 app.config.from_object(config) @app.route('/login', methods=['POST', 'GET']) def base_login(): form = BaseLogin() # 判斷驗證提交是否通過 if form.validate_on_submit(): flash(form.name.data + '|' + form.password.data) return '表單數據提交成功' else: return render_template('login.html', form=form) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run(debug=True)
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Flask_WTF</title> </head> <body> <style type="text/css"> .div1 { height: 180px; width: 380px; border: 1px solid #8A8989; margin: 0 auto; } .input { display: block; width: 350px; height: 40px; margin: 10px auto; } .button { background: #2066C5; color: white; font-size: 18px; font-weight: bold; height: 50px; border-radius: 4px; } </style> <div class="div1"> <form action="/login" method="post"> <!--啟動CSRF--> {{ form.hidden_tag() }} {{ form.name(size=16, id='name', class='input') }} {% for e in form.name.errors %} <span style="color: red">{{ e }}</span> {% endfor %} {{ form.password(size=16, id='password', class='input') }} {% for e in form.password.errors %} <span style="color: red">{{ e }}</span> {% endfor %} <input type="submit" value="登錄" class="input button"> </form> </div> </body> </html>
2 使用Flask上傳文件
在Web開發時,經常需要實現文件上傳功能。可以以普通方式進行文件的上傳,上傳過程一般要檢查上傳的文件格式是否符合要求,文件保存時注意絕對路徑和相對路徑。
Flask文件上傳比較簡單,需要注意以下3點要求:
- 一個標簽被標記有enctype=multipart/form-data,并且在里面包含一個input type=file
- 服務器端應用通過請求對象上的
files
字典訪問文件。 - 使用文件的
save()
方法將文件永久地保存在文件系統上的某處。 - 注意:表單中必須要求enctype=“multipart/form-data”,否則上傳文件無效。一般可以寫成<form action="" method=“post” enctype=“multipart/form-data”
import os
, from os import path
指的是導入os模塊及os模塊下的path方法。方法下相關屬性如下:
-
os.path.sep
: windows下路徑分隔符是反斜杠\
; -
os.path.altsep
: linux下路徑分隔符是/
根目錄: -
os.path.curdir
當前目錄 : -
os.path.pardir
父目錄 :os.path.abspath(path)
- 絕對路徑:
os.path.join()
注意:什么是文件分隔符?將表格轉換為文本時,用分隔符標識文件分隔的位置或將文本轉換成表格時,用其標識新行或新列的起始位置。不同操作系統下文件分隔符是不同的,Windows中是"", Linux中是"/"
# @time:2020/11/8 21:48 # Author:Small-J # 導入secure_filename方法,將中文文件名傳給secure_filename from werkzeug.utils import secure_filename from flask import Flask, render_template, request import os from os import path app = Flask(__name__) # 指定該路由可以使用的請求方式,get和post請求兩種方式 @app.route('/', methods=['POST', 'GET']) def hello_world(): # method : 請求的方法 if request.method == 'GET': return render_template('upload.html') else: # request.files:代表著獲取文件流 # 這里接受的file指的是對應name對應的值 f = request.files['file'] # 去掉其中文命名 filename = secure_filename(f.filename) # save : 字節保存語句拼接 f.save(path.join('static/uploads', filename)) return "上傳文件成功!" if __name__ == '__main__': app.run(debug=True)
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>文件上傳</title> <style type="text/css"> .div1 { height: 180px; width: 380px; border: 1px solid #8A8989; margin: 0 auto; } .input { display: block; width: 250px; height: 30px; margin: 10px auto; } .button { background: #2066C5; color: white; font-size: 18px; font-weight: bold; height: 30px; border-radius: 4px; } </style> </head> <body> <div class="div1"> {# 當選擇文件上傳的時候,我們需要使用到enctype,否則是無法上傳使用的 #} {# multipart/form-data:在使用包含文件上傳控件的表單時,必須使用該值 #} <form action="" method="post" enctype="multipart/form-data"> <input type="file" name="file" class="input"> <input type="submit" value="上傳" class="input button"> </form> </div> </body> </html>
上傳文件
3 Cookie的使用
Cookie有時也記作Cookies,它現在經常被大家提到,那么到底什么是Cookies?它有什么作用呢?Cookies是一種能夠讓服務器把少量數據儲存到客戶端的硬盤或內存,或是從客戶端的硬盤讀取數據的一種技術。當你再次瀏覽某網站時,瀏覽器將存放于本地的用戶身份信息遞交給服務器,服務器就可以識別用戶的身份
3.1 Cookie的基本概念
當用戶訪問服務器并登錄成功后,服務器向客戶端返回的一些數據(Cookie),客戶端將服務器返回的Cookie數據保存在本地,當用戶再次訪問服務器時,瀏覽器自動攜帶Cookie數據給服務器,服務器便自動訪問者的身份信息。
Cookie基本的語法:set_cookie(name, value, expire, path, domain, secure)
參數 | 描述 |
---|---|
name | 必需項,規定Cookie的名稱 |
value | 必需項,規定Cookie的值 |
expire | 可選項,規定Cookie的有效期 |
path | 可選項,規定Cookie在當前Web下哪些目錄有效 |
domain | 可選項,規定Cookie作用的有效域名 |
secure | 可選項,規定是否通過安全的HTTPS連接來傳輸Cookie |
3.2 Cookie的基本使用
我們在Flask中自定義Cookie,實際上就是在相應Response的Set-Cookie
字段中新增加自定義的鍵值對。而獲取Cookie,就是在請求Request中通過鍵獲取對應的值,所以,在工程中必須引入Request和Response模塊。
設置Cookie
設置Cookie主要有兩種方法,一種是通過Response
對象設置,另一種是通過直接設置表單頭來實現。
# @time:2020/11/9 13:20 # Author:Small-J from flask import Flask, request, Response app = Flask(__name__) @app.route('/') def set_cookie(): # 創建響應 resp = Response("設置Cookie!") # 設置Cookie名稱 resp.set_cookie('username', 'Small-J') return resp if __name__ == '__main__': app.run(debug=True)
查看Cookie
查看已經設置好的Cookie,可以通過request.cookies.get來得到
@app.route('/get_cookie') def get_cookie(): # 可通過請求cookies方式來獲取 username = request.cookies.get('username') return username
刪除Cookie
刪除已經設置好的Cookie,可以通過delete_cookie()
來完成。delect_cookie
括號中對象為被刪除的對象名,比如delect_cookie("username")
@app.route('/del_cookie') def del_cookie(): # 創建響應 resp = Response('刪除Cookie') # 刪除Cookie resp.delete_cookie("username") return resp
4 Session的使用
Session是基于Cookie實現的,保存在服務器的鍵值對(session[‘name’] = ‘value’)中。同時,在瀏覽器的Cookie也對應一個相同的隨機字符串,用來再次請求的時驗證
注意:Session是存儲在服務器中的,Cookies是儲存在瀏覽器本地中,而Flask的Session是基于Cookies,Session是經過加密保存在Cookies中。
4.1 Session的基本配置
因為Flask的Session是通過加密之后放在了Cookie中。有加密就有密鑰用于解密,所以,用到了Flask的Sessio模塊就一定要配置SECRET_KEY這個全局宏。一般將SECRET_KEY設置為24位的字符。我們可以自己設定一個隨機字符串,例如:
app.config['SECRET_KEY'] = XXXXXXX
我們也可以引入OS模塊中,自動產生一個24位的隨機字符串函數。這種方法有個不足之處,就是服務器每次啟動之后這個SECRET_KEY的值是不一樣的,會造成Session驗證失效,用戶只有重新登錄。
4.2 Session的基本使用
設置Session
設置Session主要是通過session['name'] = 'value'
方法來完成,name代表的是變量名稱,value代表的是變量的值
# @time:2020/11/9 16:59 # Author:Small-J from flask import Flask, session import os app = Flask(__name__) # 產生SECRET_KEY值 app.config['SECRET_KEY'] = os.urandom(24) @app.route('/') def set_session(): session['username'] = 'Small-J' return 'Session設置成功'
獲取Session的值
獲取Session的值有兩種方法
-
session['name']
: 如果內容不存在,將會報異常 -
session.get('name')
: 如果內容不存在,將會返回None
class GetSession(views.View): """獲取session的值""" def dispatch_request(self): username = session.get('username') return username or "Session為空" # 添加路由規則 app.add_url_rule(rule='/get_session', endpoint='get_session', view_func=GetSession.as_view('session'))
刪除Session的值或清空Session所有值
刪除單個Session的值,可以使用Session.pop('key')
這個方法,如果清除多個Session的值,可以使用Session.clear
方法
class DelSession(views.View): """刪除session的值""" def dispatch_request(self): # 刪除單個session session.pop('username') # 清空 # session.clear() return 'Session被刪除'
設置Session的過期時間
如果沒有指定Session的過期時間,那么默認就是瀏覽器關閉后自動結束,即關閉瀏覽器失效。session.permanent=True
在Flask下則可以將有效期延長至一個月。下面的方法可以配置具體多少天的有效期。
如果設置了Session的permanent屬性為True,那么過期時間是31天。
可以通過給app.config設置PERMANENT_SESSION_LIFETIME
來更改過期時間
在實際項目開發中可能還有一種需求,就是指定Session的失效時間為3天、7天、10天等整數天數的情況,這里主要用到了一個持續久化的會話生成的時間(實質就是Session會話的有效期)PERMANENT_SESSION_LIFETIME
,作為一個datetime.timedelta
對象
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
原文鏈接:https://blog.csdn.net/qq_37662827/article/details/109583468
相關推薦
- 2024-01-31 在 Nginx 配置中,root 和 alias 指令的區別是什么
- 2022-12-15 Go字典使用詳解_Golang
- 2022-07-15 使用Android原生WebView+Highcharts實現可左右滑動的折線圖_Android
- 2022-11-09 React特征學習Form數據管理示例詳解_React
- 2022-07-10 手動實現function isInstanceOf(child,Parent)
- 2022-04-19 npm install運行原理分析
- 2022-02-25 C語言函數棧幀的創建和銷毀介紹_C 語言
- 2023-11-15 latex表格添加注腳;對表格的內容進行注釋
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支