iT邦幫忙

2021 iThome 鐵人賽

DAY 14
1
自我挑戰組

月光下的Flask之旅系列 第 14

Day 14 Flask 傳入參數

  • 分享至 

  • xImage
  •  

在網頁中不可能只是按照設定好的 URL 去取得網頁頁面,在許多時候都需要帶入不同的參數去取得不同的資料,所以這篇就要來講一下如何接收傳入的參數。

URL

參數位於 URL 的路徑中,需要從 URL 中間抓參數的,可以使用這個方式:

# 提醒一下,這邊的<>是需要帶入的
@app.route('/<type:name>')
def <function name>(<name>):
    # TODO

其中 name 是必要的,下方的 function 內要使用必須在括號內填入名稱,type 跟 : 不一定需要(冒號後面不可以有空格)。而類型有下列 5 種:

Type Description
string 文字類型(默認類型)
int 整數
float 浮點數
path 跟 string 差不多,但可以有斜線 /
uuid UUID 字符串
@app.route('/home/<username>')
def home_page(username):
    return f"Hello {username}"

@app.route('/add/<int:a>/<int:b>')
def add(a, b):
    return str(a + b)

如果要測試的話,就在 POSTMAN 或瀏覽器中輸入 http://localhost:5000/home/Mike or http://localhost:5000/add/1/2 ,這樣你就會的到回傳的值,當然也可以把那個位置的參數換掉一樣會得到相應的結果。

大概就是這樣。

request

因為有些參數例如帳號密碼直接寫在 URL 上並不好,或是連結必須跟著不同使用情況跟著改變也不方便,所以這種情況必須採用其他方式傳輸參數。

那要怎麼傳輸資料跟取得資料呢?

首先要 import request(from flask import request),然後根據不同傳輸參數的方式,去使用相應的方法取得資料。這邊先介紹兩種最基本的傳輸參數的方式以及它們個別取資料的方法,還有一個超好用的通用取參數方式。

GET / args

第一個是最最常用傳輸的方式就是 GET,傳輸參數的方式就是在 URL 後面加上問號 ? 後,再加上 key=value,如果有多筆資料,則用 and & 連接起來(POSTMAN 可以在 Day 12 中間的藍色區域選擇 Params 然後輸入 key 與 value)。

程式的部分需要這樣子寫:

# 記得 from flask import request
@app.route('/get-value', methods=['GET'])
def get_value():
    # 方法 1
    return request.args['input_value']

    # 方法 2, 不帶預設值
    return request.args.get('input_value')
    
    # 方法 2, 帶預設值
    return request.args.get('input_value', 'No input')

上下兩種方式都可以使用,不過下面的方式可以在沒有接到輸入時能夠有個預設值。

如果要測試的話,就在 POSTMAN 的 URL 輸入 http://localhost:5000/get-value ,然後在中間(再說一次,選 Params)的輸入參數部分 key 輸入 input ,value 輸入 test (其實這兩個叫啥都可以,key 跟程式裡面寫得對的上就好,value 隨便填),然後按 Send ,就會得到回傳結果。

第一種方式雖然不需要改變基本的 URL (? 前面那陀),但是帶的參數還是跟在 URL 的後面,若是需要傳送一些比較機的資料還是不好,所以就有了這個方式。

POST / from

第二種方式是 POST ,這個方式是不會將傳輸的資料直接寫在 URL 上面,不過就無法通過瀏覽器輸入 URL 的方式測試結果了,需要再 POSTMAN 中選擇 Body -> form-data 輸入 key 與 value。

程式的部分需要這樣子寫:

@app.route('/post-value', methods=['POST'])
def post_value():
    # 方法 1
    return request.args['input_value']

    # 方法 2, 不帶預設值
    return request.args.get('input_value')
    
    # 方法 2, 帶預設值
    return request.form.get('input_value', 'No input')

跟前面一樣,都可以使用,方法 2 一樣可以帶預設值。

如果要測試的話,就在 POSTMAN 的 URL 輸入 http://localhost:5000/post-value ,然後在中間(使用 POST 記得選 Body -> x-www-form-urlencoded)的輸入參數部分 key 輸入 input ,value 輸入 test (其實這兩個叫啥都可以,key 跟程式裡面寫得對的上就好,value 隨便填),然後按 Send ,就會得到回傳結果。

any / values

最後要介紹一個超級大好用的方式,不管 GET 還是 POST 還是什麼(對,不只這兩種方式,但要詳細介紹的話又可以開另一篇了,之後講 RESTful 會快速介紹過一遍)都可以接到,那就是 values (要有 s)。

@app.route('/any-value', methods=['GET', 'POST'])
def any_value():
    # 方法 1
    return request.values['input_value']

    # 方法 2, 不帶預設值
    return request.values.get('input_value')
    
    # 方法 2, 帶預設值
    return request.values.get('input_value', 'No input')

跟前面一樣,都可以使用,方法 2 一樣可以帶預設值。

這個方法超好用,不管是使用哪種方式傳值都可以接到。例如 GET 傳值:

POST 傳值:

*如果需要判斷傳值方式可以使用 request.method == '<method>' 來判斷

JSON

除了上面這幾種傳值方式之外,還有一種也很常用的傳值方式就是 JSON,尤其常用在傳遞大量參數上。那麼要如何使用以及處裡呢?

首先,先來看程式部分:

@app.route('/JSON-value', methods=['POST'])
def JSON_value():
    # 判斷是不是 JSON
    # 根據 HTTP Header 的 Content-Type 有無 application/json
    if request.is_json:
        # 解析 JSON 資料為 dict ,若不是 JSON,則返回 None
        data = request.get_json()
        # 從資料中獲取值
        result = data.get('input_values', None)
    else:
        result = 'Not JSON Data'
    return result

接著在 POSTMAN 輸入 URL http://localhost:5000/JSON-value、選擇 POST、選擇 Body -> rawTextJSON 、在中間的框內輸入:

{
    "input_value": "test"
}

最後再按下 Send,就可以看到回傳了輸入的值。

url_for

上一篇有講到可以使用 url_for 取代掉長長的網址對吧,那如果要帶參數的話要怎麼辦?其實 url_for 是可以帶參數的,不過只能用在 URL 位置中跟 GET 方法,

# URL path parameter
url_for('home_page' , username='Mischau')

# GET method pass value
url_for('get-value', input_value='test input')

url_for 大概就這樣。

File upload

如果希望使用者傳遞的不只是參數,還可以是檔案(檔案的話只能使用 POST 上傳喔)。那這時候要怎麼做呢?直接看做法:

from flask import Flask, request
from werkzeug.utils import secure_filename
import os


CONFIGS = {
    'ENV': 'development',
    'DEBUG': True,
    'UPLOAD_FOLDER' = './file_uploads',  # 要先建好這個資料夾喔,在專案根目錄
    'ALLOW_EXTENSIONS': ['txt', 'pdf', 'png', 'jpg']
}

app = Flask(__name__)
app.config.form_mapping(CONFIGS)


# 判斷副檔名是否允許上傳
def is_allow_extensions(filename):
    return ('.' in filename) and (filename.split('.')[-1].lower() in app.config['ALLOW_EXTENSIONS'])


@app.route('/file-upload', methods=['POST'])
def file_upload():
    # 這邊 request.files['<key name>'] 的 key name 等一下會用到
    f = request.files['files']
    filename = secure_filename(f.filename)
    if is_allow_extensions(filename):
        f.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return 'success'
    else:
        return 'error'

沒錯,這樣就可以了,來開個 POSTMAN 測試看看吧(method 選 POST;輸入參數選 Body -> form-data , 檔案先放在 C:/Users/<user name>/Postman/files 裡面;KEY 格式選 File,如果沒看到File 的選項,滑鼠滑過去就會看到了;VALUE 選擇檔案後按 Send)!

如果出現 success ,就可以看一下是不是有正確上傳了。

那麼就大概這樣,接收傳到後端的參數並不會很難,注意一下 KEY name 就可以了。

大家掰~掰~


上一篇
Day 13 Flask Route
下一篇
Day 15 Flask 回傳參數
系列文
月光下的Flask之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言