Flask RESTful API 開發----基礎篇 (1)

本文首發於Gevin的博客
原文連接:Flask RESTful API 開發----基礎篇 (1)
未經 Gevin 受權,禁止轉載python

From zoomy
From zoomy

0. 前言

接下來一段時間,Gevin將開一個系列專題,講Flask RESTful API的開發,本文是第1篇《Flask RESTful 基礎》,本系列文章列表以下:git

1. RESTful 簡介

我在博文《RESTful 架構風格概述》和《RESTful API 編寫指南》中曾詳細論述過我對RESTful的理解,以及規範的RESTful API開發須要涉及的內容,本節摘錄幾條重點內容,爲下文作鋪墊:github

  1. RESTful 是面向資源的,每一個資源至少有一個url與之對應
  2. 統一數據交互接口,即經過http的GET, POST, PUT(or PATCH), 和 DELETE 進行資源的獲取、建立、更新和刪除
  3. 資源(數據)以文本形式在網絡上傳輸,一般以json或xml格式爲載體
  4. 無狀態(之後講認證時再展開論述)

2. Flask 對RESTful 架構風格的支持

Flask RESTful 開發相關的庫不少,我也收集過一些(collection在此,不按期更新),其實,與Django不一樣,Flask原生對RESTful的支持已經作的很好,不借助這些extension,同樣能夠開發出足夠好的RESTful API,並且沒有這些extension的束縛,咱們能夠在開發過程當中,配合使用Flask生態中處理相應問題最好的extension,或者咱們本身最上手的extension,這也更加符合Flask的philosophy。Gevin在Flask RESTful 開發中,不使用各種flask rest擴展的主要緣由,正是每一個擴展都有不盡如意之處。json

那麼,咱們就來看一下Flask原生是如何支持RESTful開發的。flask

(注:Django RESTful開發主要基於Django REST Framework,Django的DRF理念對我一直很受用,我在Flask開發和Flask RESTful API開發中,借鑑了不少Django的設計理念。所以,對於如何作好Flask開發,Gevin有個觀點是:不妨從Django的開發作起~ :P)api

2.1 Flask對HTTP方法的支持

Flask原生支持全部的HTTP方法,如RESTful API中最經常使用的GET, POST, PUT, PATCHDELETE,這些不需贅述解釋,直接上代碼便可:restful

@app.route('/http-method-test/', methods=['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])
def http_method_example():
    if request.method == 'GET':
        return 'Send request with `GET` method'
    elif request.method == 'POST':
        return 'Send request with `POST` method'
    elif request.method == 'PUT':
        return 'Send request with `PUT` method'
    elif request.method == 'PATCH':
        return 'Send request with `PATCH` method'
    elif request.method == 'DELETE':
        return 'Send request with `DELETE` method'複製代碼

另一種方式是採用Flask的MethodView:網絡

class HttpMethodExample(MethodView):
    def get(self):
        return 'Send request with `GET` method'

    def post(self):
        return 'Send request with `POST` method'

    def put(self):
        return 'Send request with `PUT` method'

    def patch(self):
        return 'Send request with `PATCH` method'

    def delete(self):
        return 'Send request with `DELETE` method'

app.add_url_rule('/http-method-test2/', view_func=HttpMethodExample.as_view('http_method_example2'))複製代碼

2.2 Flask 對序列化與反序列化的支持

RESTful 開發時,數據的載體一般爲jsonxml格式的文本,隨着RESTful的不斷髮展,json更是成爲了RESTful API 數據的主流載體。而Flask自己,已經對json的支持已經很是好了。架構

2.2.1 序列化

RESTful API開發中的序列化,經過包含了如下操做:app

  1. 將Python native格式的數據(如dict和list)轉換爲文本數據(如json或xml)
  2. 將文本數據做爲請求的response返回給客戶端,response的http header裏要同時附加application/json這個mimetype

這兩步操做,Flask提供的一個快捷函數jsonify()能直接完成,其詳情正以下面的Flask官方文檔所述:

This function wraps dumps() to add a few enhancements that make life easier. It turns the JSON output into a Response object with the application/json mimetype. For convenience, it also converts multiple arguments into an array or multiple keyword arguments into a dict. This means that both jsonify(1,2,3) and jsonify([1,2,3]) serialize to [1,2,3].

很簡單的事情,不應說這麼多,直接上代碼示例吧:

class SerializationExample(MethodView):
    def get(self):
        option = request.args.get('option')

        if option == 'list1':
            return self.test_list()
        if option == 'list2':
            return self.test_list2()
        if option == 'dict1':
            return self.test_dict1()
        if option == 'dict2':
            return self.test_dict2()
        if option == 'dict3':
            return self.test_dict3()


        msg = {
            'info': '`option` is needed in url as a url parameter',
            'avilable option values': 'list1, list2, test_dict1, test_dict2, test_dict2'
        }
        return jsonify(msg)



    def test_list(self):
        data = [{'a':1, 'b':2}, {'c':3, 'd':4}]
        return jsonify(result=data)

    def test_list2(self):
        data = [1,2,3,4,5,6,7,8]
        return jsonify(data)


    def test_dict1(self):
        data = {'a':1, 'b':2, 'c':3}
        return jsonify(data)

    def test_dict2(self):
        data = {'a':1, 'b':2, 'c':3}
        return jsonify(**data)

    def test_dict3(self):
        data = {'a':1, 'b':2, 'c':3}
        return jsonify(result=data)

app.add_url_rule('/serialization/', view_func=SerializationExample.as_view('serialization'))複製代碼

上面代碼的重點即,那幾個以test_開頭的函數,序列化的表現形式無外乎這幾種。

2.2.2 反序列化

反序列化,即把文本形式的數據轉換爲Python native類型數據的過程。在RESTful API開發時,Flask內置的get_json()方法,可以把request中的json數據,轉換爲Python標準庫中的dict或list。

Parses the incoming JSON request data and returns it. By default this function will return None if the mimetype is not application/json, but this can be overridden by the force parameter.

If parsing fails the on_json_loading_failed() method on the request object will be invoked.

示例代碼:

@app.route('/deserialization/', methods=['get', 'post'])
def deserialization():
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            return 'No json data found', 400

        result = {
            'json data in request': data
        }
        return jsonify(result)

    return 'Please post json data'複製代碼

注:

Flask原生的序列化和反序列化方法,都是針對目前RESTful API 開發時最流行的json格式的,且只能作jsondictlist的相互轉換,若是想序列化或反序列化對象實例,須要藉助其餘方法,這個會在之後的文章中作進一步解釋。

3. What's More

  • 我在GitHub上的項目restapi_example,存放了本系列內容的完整源碼,你們能夠隨意查閱。

  • 本章涉及的代碼,完整示例請查看上面項目的chapter1分支

  • RESTful API 開發時,測試API可用工具Postman

  • 下一講預告:Gevin將結合一個具體的應用實例,介紹RESTful API的設計與實現

相關文章
相關標籤/搜索