Flask-1-04-Request

在開始學習代碼以前先介紹一個工具叫作Postman :

對就長上面那樣,它是一款很是適合開發人員使用的調試工具,能夠根據你發起的請求攜帶一些參數,起碼我如今是這麼理解的,各類你要發送給服務端的參數

那麼就進入今天的正題:

獲取請求從參數:

首先咱們須要從框架中導入,Flask爲咱們準備的request,它就是Flask中表示當前請求的request對象。request對象中保存了一次Http請求的信息

首先咱們經過Postman爲咱們發起一條請求信息,在這以前,咱們須要先定義一個視圖,讓它找到請求的路徑

# coding:utf-8
from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    return 'test ok'

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

不重要的注意:爲了讓文檔看起來不那麼冗長,我選擇性的減小了空行html

經過上面一系列的操做大體應該瞭解若是發送一次請求,接下來的有些操做,有多是文字形容不太清楚的。因此仔細的看一下截圖的每個帶有選框和你下載Postman不同的地方。前端

Request的經常使用屬性

  • form

    一個包含解析過的從 POST 或 PUT 請求發送的表單對象的 MultiDict 。請注意上傳的文件不會在這裏,而是在 files 屬性中。python

  • args

    一個包含解析過的查詢字符串( URL 中問號後的部分)內容的 MultiDict 。json

  • values

    一個包含 form 和 args 所有內容的 CombinedMultiDict 。flask

  • cookies

    一個包含請求中傳送的全部 cookie 內容的 dict 。後端

  • stream

    若是表單提交的數據沒有以已知的 mimetype 編碼,爲性能考慮,數據會不經修改存儲在這個流中。大多數狀況下,使用能夠把數據提供爲字符串的 data 是更好的方法。流只返回一次數據。api

  • headers

    進入請求的標頭存爲一個相似字典的對象。瀏覽器

  • data

    若是進入的請求數據是 Flask 不能處理的 mimetype ,數據將做爲字符串存於此。服務器

  • files

    一個包含 POST 和 PUT 請求中上傳的文件的 MultiDict 。每一個文件存儲爲FileStorage 對象。其基本的行爲相似你在 Python 中見到的標準文件對象,差別在於這個對象有一個 save() 方法能夠把文件存儲到文件系統上。cookie

  • environ

    底層的 WSGI 環境。

  • method

    當前請求的 HTTP 方法 (POST , GET 等等)

 

首先咱們經過Postman發送一個from表單請求,先寫好後臺接收的視圖,而後再發起請求

# coding:utf-8
# request中包含了前端發送過來的全部請求數據
from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    # 接收客戶端請求過來的數據
    # 經過requset.form能夠直接提取請求體中的表單格式的數據, 是一個相似字典的對象
    name = request.form.get('username')
    pwd = request.form.get('password')
    return 'username = %s, password = %s' % (name, pwd)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

一個不重要的注意:請把注意點放在Flask框架上,這個Postman不是重點,主要是後端經過request接收前端發送過來的數據纔是重點,理清request纔是最主要的。你也能夠經過頁面發送到視圖,你任何能夠發起請求的方式都是能夠的不僅僅只有Postman

經過代碼能夠看出,咱們經過request.form來接受前端發送過來的表單數據,接受的是相似字典的一個對象,既然是字典咱們也能夠經過這種方式來賦值給變量 request.form['username'],可是並不推薦後端來這麼作。由於使用get()方法獲取,就算找不到最多也就是返回一個None,不會對你的程序形成什麼沒必要要的錯誤,可是若是這裏你經過request.form['username']這種方式獲取得話,在Web程序當中會直接返回一個400的狀態碼,會給你爆出一個錯誤,影響你的頁面的流暢,若是你屬於交付以後的狀態,那麼你的甲方必定會來找你麻煩,爲了不沒必要要的麻煩,請善待你的程序,避免沒必要要的Bug,那麼接下來就來展現一下這些問題,代碼會很是的像,請仔細觀看

 

from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    name = request.form['username']  # 注意這裏爲更改代碼
    # name = request.form.get('username')
    pwd = request.form.get('password')
    return 'username = %s, password = %s' % (name, pwd)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

 

接下來在看一下若是經過request.form.get('username')這種方式接受前端發送過來的請求參數出現找不到的狀況會是友好的嗎?

from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    # name = request.form['username']
    name = request.form.get('username')  # 此次是經過get()方法接受數據
    pwd = request.form.get('password')
    return 'username = %s, password = %s' % (name, pwd)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

若是表單中傳過來同名的鍵,那麼接受結果會如何呢?我在請求中傳入了兩個username分別是不一樣的值

經過返回的結果能夠看出,返回給咱們的是第一個找到的username的值,這裏若是真的都想獲取到,能夠經過getlist()方法來接受請求的同名的鍵

from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    # 經過get方法只能拿到多個同名參數的第一個
    name = request.form.get('username')
    pwd = request.form.get('password')
    # 經過getlist() 能夠獲取多個
    name_list = request.form.getlist('username')
    return 'username = %s, password = %s, username_list = %s' % (name, pwd, name_list)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

注意:確定會有小夥伴,會看見在字符串前面有一個u,這裏簡單的擴展一下,由於在Python2中,字符串類型默認是兩種,一種是str,還有一種Unicode,這裏展示的就是Unicode字符串,在Python3中已取消。是一個好吃的雞肋。不用太在乎,若是之後須要操做它,會在演示如何去使用

若是是請求體的數據不是表單格式的(如json格式),能夠經過request.data獲取

from flask import Flask, request
app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    # 若是是請求體的數據不是表單格式的(如json格式),能夠經過request.data獲取
    json_data = request.data
    return 'json_data = %s' % json_data

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

 POST請求方式也是能夠在地址欄裏傳遞參數的,格式:192.168.3.20:5000/index?age=30&city=harbin

from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    # args是用來提取url中的參數(查詢字符串)
    age = request.args.get('age')
    city = request.args.get('city')
    return 'age : %s, city : %s' % (age, city)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

一個不重要的注意:還有不少接受方法會在必要的時候引入

 

 

上傳文件


用Flask處理文件上傳很是的簡單,只須要經過一個save()方法,就能夠把文件保存到服務器的文件系統中,固然這也是一個很是危險的操做,以後會有介紹,已上傳的文件會存儲在內存或文件系統中一個臨時的位置,你能夠經過請求對象的files屬性來訪問他們,每個上傳的文件都會存儲在這個字典中,它跟Python中的file對象基本一致。你也能夠經過Python的方法來處理文件寫入到本地的方法來完成這個操做

這裏咱們依然使用Postman來完成這個請求,可是若是你使用的是html頁面,必定要確保在HTML表單中設置enctype="multipart/form-data" 屬性,否則你的瀏覽器根本不會發送這個文件,咱們仍是先來完成後臺的代碼:

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['POST'])
def upload():
    # 使用files屬性來訪問保存在內存中或者文件系統中一個臨時的位置的這個上傳文件
    file_obj = request.files.get('pic')
    # 使用save方法來保存剛剛獲取的上傳文件
    file_obj.save('/home/python/圖片/upload.jpg')
    return '文件上傳完畢'

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

給大家展現一下上傳的圖片,屌絲氣質暴露無遺,哈哈哈

能夠看出在Flask中上傳一個文件真的很簡單,接下來,咱們就討論爲何直接使用save()方法會很危險,並且我在官方提供的文檔中找到一個很是好的解決方案,能夠研究一下,實在看不懂也是無所謂的。文件上傳的基本概念實現上很是簡單,流程是:

  1. <form> 標籤中有定義一個 enctype=multipart/form-data ,而且在裏面包含一個 <input type=file> 標籤。

  2. 服務端應用經過請求對象上的 files 字典訪問文件。

  3. 使用文件的 save() 方法將文件永久地保存在文件系統上的某處。

這樣就完成了,可是你永遠都沒法保證在瀏覽器訪問你網站的那我的,不想搞些事情,好比XSS問題的HTML文件(跨站腳本攻擊【XSS】),因此咱們要限制上傳文件的後綴,來儘可能保證不要傳入一些腳本文件或者別的什麼東西。

# coding:utf-8
# request中包含了前端發送過來的全部請求數據
from flask import Flask, request
from werkzeug import secure_filename
import os

# 存儲上傳文件的路徑
UPLOAD_FOLDER = '/home/python/圖片/'
# 容許的文件類型
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
# 將路徑添加到配置中
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


# 用來驗證用戶上傳的文件是不是容許的
def allowed_file(filename):
    # 判斷文件中是否有. and 用.只截取1次文件名獲得的一個列表,選擇列表第二個值看是否屬於被容許的文件類型
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


@app.route('/', methods=['POST'])
def upload():
    # 使用files屬性來訪問保存在內存中或者文件系統中一個臨時的位置的這個上傳文件
    file_obj = request.files.get('pic')
    # 判斷用戶是否上傳了文件 和 文件是不是容許的類型
    if file_obj and allowed_file(file_obj.filename):
        filename = secure_filename(file_obj.filename)
        file_obj.save(os.path.join(UPLOAD_FOLDER, filename))
        return '文件上傳完畢'
    else:
        return '文件上傳失敗'
    
    
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

經過Postman上傳一個帶有圖片的請求,這裏咱們從新上傳了一個別的文件

這裏看出上傳文件是沒有問題的,如今咱們來測試一下若是上傳一個不被容許的文件類型,是否會幫咱們阻攔

這裏就能夠阻攔咱們不想看到的文件被上傳,若是有人想問,文件裏包含不少.會不會被阻攔,答案顯然是不會,只要是在容許的類型裏,都是能夠上傳的,由於rsplit()是從字符的最後面開始截取的,並且設置了只截取一次 rsplit('.', 1) 【註釋 .表明用.截取,1表明截取1次】

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息