1 請求報文和響應報文
打開瀏覽器,當我們輸入一個url,點擊訪問的時候會向目標服務器發送一個HTTP請求,請求的的時候會發生什么呢,會經過os七層,這里我們不贅述os七層通訊原理,可以理解為通過url我們請求目標服務器的一段具體的資源,可以理解為發送了一個請求,一個請求的本質就是向目標服務器上面發送了一些數據,這種瀏覽器於服務器之間交互的數據被稱為報文。
-
請求報文:請求時瀏覽器發送的數據稱為請求報文
-
響應報文:服務器收到了請求返回給瀏覽器的數據稱為響應報文
✔提示:這里我們們是BS架構去講解, BS架構就是瀏覽器和后端服務器的交互,CS架構是客戶端和服務端的交互,BS架構可以理解為CS架構的一個具體實現。瀏覽器就是客戶端,后端服務器就是服務端。
報文中的GET請求和POST請求
- GET提交的數據會放在URL之后,以?分割URL和傳輸數據,參數之間以&相連,如EditBook?name=test1&id=123456.
- POST方法是把提交的數據放在HTTP包的請求體中.
- GET提交的數據大小有限制(因為瀏覽器對URL的長度有限制)
- POST方法提交的數據沒有限制。
- GET與POST請求在服務端獲取請求數據方式不同。
報文實例:
'''
GET請求報文
# 請求首行
GET / HTTP/1.1\r\n
# get請求后面的參數
GET /?name=lqz&age=18 HTTP/1.1\r\n
# 請求頭
Host: 127.0.0.1:8008\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n'
# 請求體(get請求,請求體為空)
'''
'''
POST請求報文
# 請求首行
POST /?name=lqz&age=18 HTTP/1.1\r\n
# 請求頭
Host: 127.0.0.1:8008\r\nConnection: keep-alive\r\n
Content-Length: 21\r\nCache-Control: max-age=0\r\n
Origin: http://127.0.0.1:8008\r\nUpgrade-Insecure-Requests: 1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\n Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8008/?name=lqz&age=18\r\n
Accept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n
# 請求體
name=lqz&password=123'
'''
2 request對象
2.1什么是request對象?
request對象封裝解析了請求報文中的數據,其大部分功能是由依賴包werkzeug完成的,並且每個request對象都是線程隔離的,保證了數據的安全性。
2.2為什么要有request對象?
request對象解決了很多問題,各種請求的方法以及請求參數的格式都不一致,所以flask幫我們做了一個request對象,專門去解析各種方法以及各種格式的請求,以便於去開發使用。
2.3 requst對象的常用方法
request對象使用需要從flask模塊中導入
from flask import Flask, request
2.3.1 使用request屬性獲取url
訪問: http://127.0.0.1:5000/student_list/?name=mark :
表2-1 使用request的屬性獲取url
屬性 | 解析值 | 屬性 | 解析值 |
---|---|---|---|
path | u‘/student_list/’ | base_url | u'http://127.0.0.1:5000/student_list/' |
full_path | u‘/student_list/?name=mark’ | url | u'http://127.0.0.1:5000/student_list/?name=mark' |
host | u'127.0.0.1:5000' | url_root | u'http://127.0.0.1:5000/' |
host_url | u'http://127.0.0.1:5000/' |
request的解析結果如下。
@app.route('/student_list/')
def student_list():
print(request.path) # 輸出 /student_list/
print(request.full_path) # 輸出 /student_list/?name=mark
print(request.host) # 輸出 127.0.0.1:5000
print(request.host_url) # 輸出 http://127.0.0.1:5000/
print(request.base_url) # 輸出 http://127.0.0.1:5000/student_list/
print(request.url) # 輸出 http://127.0.0.1:5000/student_list/?name=mark
print(request.url_root) # 輸出 http://127.0.0.1:5000/
return 'request.urldemo測試'
2.3.2 其他request對象常用的屬性和方法。
request里面有諸多的方法,先對requests這些方法有個初步印象,隨着我們日后的學習會慢慢接觸到這些request常用的方法。
3 GET和post的實例:
3.1 常見的HTTP方法見下表:
請求 | 說明 | 請求 | 說明 |
---|---|---|---|
GET | 獲取服務器資源 | DELETE | 刪除服務器資源 |
POST | 處理服務器資源 | PATCH | 在服務器更新資源(客戶端提供改變的屬性) |
PUT | 在服務器更新資源(客戶端提供改變后的完整資源) |
一般常用的請求為GET和POST
3.2 GET
請求:
GET請求一般用於在服務器上獲取資源,不會更改服務器的狀態。
GET實例:
@app.route('/', methods=['GET']) # 不寫methods也可以 默認就接收get請求
def demo_get():
print(request.args.get('name')) # 輸出 mark
return '{}請求'.format(request.method)
結合request對象,使用request.args屬性獲取get傳來的參數,關於args我們在上一章已經論述過了。
關鍵詞:
- 使用request.args屬性獲取get傳來的參數,關於args我們在上一章已經論述過了。
- @app.route('/', methods=['GET']) 指定瀏覽器只能以GET方法訪問服務端。
3.3 POST
請求:
POST 請求: 會給服務器提交一些數據或者文件,會對服務器的狀態產生影響。
在了解POST請求之前我們先了解一下render_termplate
3.3.1 render_template的簡單使用
from flask import Flask, request, render_template
我們暫時只簡單的理解render_template模塊可以把html文件返回給瀏覽器並渲染。
如:
server.py
from flask import Flask, request, render_template
...
@app.route('/login/',methods=['GET'])
def login():
return render_template('login.html')
...
注意:render_template()會去flask根目錄下的templates里面尋找文件,所以給的參數路徑是相對路徑。
關鍵詞:render_template()中放的文件路徑是與templates文件夾相對的路徑
templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄界面</title>
</head>
<body>
<form action="/login_request/" method="POST">
用戶:<input type="text" name="username">
密碼:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
關鍵詞
-
form標簽的
action
指定的是跳轉的頁面。並且會自動拼接成http://127.0.0.1:5000/login_request/ 也就是本項目的: ip地址+端口+/login_request/
-
form標簽的
method
指定的是以什么方法請求服務端,此案例中請求的方法為POST方法。
訪問127.0.0.1:5000/login/ 后如下圖
3.3.2 正式開始我們的POST案例:
項目目錄:
server.py
from flask import Flask, request, render_template
import config
app = Flask(__name__)
@app.route('/login_request/',methods=['POST'])
def login_request():
print(request.form.get('username')) # 'mark'
print(request.form.get('password')) # '123'
if request.form.get('username') == 'mark' and request.form.get('password') == '123':
return 'success'
else:
return 'error'
@app.route('/login/',methods=['GET'])
def login():
return render_template('login.html')
if __name__ == '__main__':
app.run()
關鍵詞:
- request.form是專門用來針對表單取數據的,在這里如果前端是以表單的形式提交的,我們可以使用request.form來取值
- @app.route() 中的 methods=['POST'] 代表只接收瀏覽器的POST請求
templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄界面</title>
</head>
<body>
<form action="/login_request/" method="POST">
用戶:<input type="text" name="username">
密碼:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
總體的邏輯是 :
- 首先訪問127.0.0.1:5000/login/,默認是get請求。
- 然后
return render_template('login.html')
返回給瀏覽器頁面。 - 然后填寫內容點擊提交,以post方式請求 http://127.0.0.1:5000/login_request/。
- 然后進入
def login_request()
視圖函數 進行邏輯判斷返回成功與否。
3.4 一個視圖函數同時可以接收GET和POST請求
我們的案例和3.3.2案例完成的業務邏輯是一樣的,相當於簡化了3.3.2的案例,把兩個視圖函數合並到一起,利用request.method
屬性可以獲取字符串格式的請求方法。來區分本次請求是GET還是POST
實例:
server.py:
from flask import Flask, request, render_template
import config
app = Flask(__name__)
@app.route('/login_inner/',methods=['POST','GET'])
def login_inner():
if request.method == 'GET': #判斷本次請求是否為get請求
return render_template('login.html')
if request.form.get('username') == 'mark' and request.form.get('password') == '123':
return 'success'
return 'error'
if __name__ == '__main__':
app.run(debug=True)
關鍵詞:
@app.route()
的methods
方法 指定該視圖函數接收瀏覽器傳過來的請求方法,可以指定多個。request.method
獲取字符串格式的請求方法
templates/login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄界面</title>
</head>
<body>
<form action="" method="POST">
用戶:<input type="text" name="username">
密碼:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
其展示效果