使用Flask+MongoDB實現基於REST的接口簡單操作
目錄
前言
1 準備工作
2 具體實現
前言
最近在搗鼓如何使用阿裏雲服務器搭建一個簡單的基於Flask框架的後端接口,剛開始為了圖方便,就直接買了一個Windows Server 2008系統服務器,這也埋下了不小的坑。
服務買下來後,會給你一個公網IP和內網IP,由於是第一次學習搭建後端接口,對於如何正確使用阿裏雲服務器,來處理好公網IP和內網IP之間的關系埋下了不小的坑,真是對應的一句話:技術的成長往往是一步一個坑。
下面簡單說一下搭建Flask服務器端遇到的問題:
首先,Flask自帶了一個服務器,直接使用很方便,不過這個服務器的性能太低,但是對於調試和學習還是綽綽有余。剛開始把代碼放到阿裏雲服務器上,並跑通後,測試接口時公網IP無法訪問,那時我以為是Flask自帶服務器的問題,即因為Flask自帶服務器原因導致無法使用公網IP訪問。
那麽,問題出現了,就要尋找解決辦法吧,網上查找資料給出參照意見:使用nginx +gunicorn來部署Flask相關服務,可以避免公網IP無法訪問問題。然後,我就去找資料,安裝gunicorn,結果運行測試時一直報錯,最後發現gunicorn不支持Windows系統,這也太坑了,早知道我當時買服務器時就不該圖方便,直接買一個基於Linux的系統了。
現在,新的問題又來了,既然不能使用nginx +gunicorn來部署Flask相關服務,那就要使用其它方式來解決吧,網上資料參照結果:使用tornado。好,那麽我又來查看學習tornado部署應用開發文檔,按照開發文檔部署完畢後,在服務器上跑通後,發現依舊不能使用公網IP進行接口訪問和測試。
到了這裏,就讓我反思,這個難道真是Flask部署應用服務器問題嗎?後來,就在網上找到了一篇關於阿裏雲公網IP無法訪問問題的文章,發現這個需要自己去阿裏雲官網上去配置設置。
即以上遇到的問題,壓根就不是Flask部署服務器問題,是自己沒有搞清楚阿裏雲服務器如何使用的問題......
具體配置設置方法見:阿裏雲服務器 ECS 訪問不了公網 ip 可能的原因及解決方法
附:
1 準備工作
導入Flask及相關擴展:
pip install flask
pip install flask-pymongo
pip install tornado(此處可選可不選。如果不選擇,直接使用Flask自帶的服務器部署即可;如果選擇,可以使用tornado部署)
MongoDB數據庫綁定服務ip地址設置(PS:如果不進行下述設置,默認ip為本機127.0.0.1地址):
打開CMD,進入MongoDB安裝的bin文件夾下,例如我的安裝目錄為:C:\Program Files\MongoDB\Server\3.2\bin
然後在CMD中輸入mongod.exe --bind_ip yourIPadress
其中參數--bind_ip意思:綁定服務IP,若綁定127.0.0.1,則只能本機訪問,不指定默認本地所有IP。(註意:其中yourIPadress填寫自己搭建服務器的內網ip地址)
具體如下圖:
開啟Flask自帶的服務器,一般使用app.run(),其中一般使用如下三個參數:host(指定ip地址,如果不填寫,默認為127.0.0.1)、port(指定使用的端口,如果不指定,默認為5000端口)、debug(開啟調試模式,默認值為Flase,即不開啟調試模式,如要開啟則可以設置為True)。
如果在服務器上搭建Flask接口相關服務,設置其中host=’0.0.0.0’表示在公網ip下的同一個局域網段所有ip都可以訪問這個服務,如果把host指定為其中一個內網ip地址,則這個局域網下所有用戶可以通過訪問這個指定的ip地址訪問Flask服務。
後面介紹可以略微看看,也相當於是了解一下nginx +gunicorn以及tornado的基本概念。也可以忽略,直接查看2 具體實現
使用nginx +gunicorn來部署Flask相關服務,即不使用Flask自帶的服務器。
看到上面的部署方式,作為初學者,不免會有新的疑問,什麽是nginx和gunicorn呢?
我自己也是新接觸的,查看了一下網上資料,大概了解了一下。
什麽是nginx呢?
摘抄自百度百科(https://baike.baidu.com/item/nginx/3817705?fr=aladdin)的一段解釋:Nginx是一款輕量級的Web 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,並在一個BSD-like 協議下發行。其特點是占有內存少,並發能力強,事實上nginx的並發能力確實在同類型的網頁服務器中表現較好,中國大陸使用nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等。
什麽是gunicorn呢?
摘抄自網上一遍文章(http://www.pythontip.com/blog/post/5155/)一段解釋:Gunicorn“綠色獨角獸”是一個被廣泛使用的高性能的Python WSGI UNIX HTTP服務器,移植自Ruby的獨角獸(Unicorn )項目,使用pre-fork worker模式,具有使用非常簡單,輕量級的資源消耗,以及高性能等特點。
Gunicorn 服務器作為wsgi app的容器,能夠與各種Web框架兼容(flask,django等),得益於gevent等技術,使用Gunicorn能夠在基本不改變wsgi app代碼的前提下,大幅度提高wsgi app的性能。
看到上面的解決辦法,試著搭建安裝,發現gunicorn不支持Windows系統,坑啊,早知道這樣就買一個Linux服務器。
使用gunicorn報錯信息:
Traceback (most recent call last): File "d:\program files (x86)\python27\Lib\runpy.py", line 174, in _run_module_as_main "__main__", fname, loader, pkg_name) File "d:\program files (x86)\python27\Lib\runpy.py", line 72, in _run_code exec code in run_globals File "E:\WorkPlace\Git_python\liu_demo\venv\Scripts\gunicorn.exe\__main__.py", line 5, in <module> File "e:\workplace\git_python\liu_demo\venv\lib\site-packages\gunicorn\app\wsgiapp.py", line 10, in <module> from gunicorn.app.base import Application File "e:\workplace\git_python\liu_demo\venv\lib\site-packages\gunicorn\app\base.py", line 12, in <module> from gunicorn import util File "e:\workplace\git_python\liu_demo\venv\lib\site-packages\gunicorn\util.py", line 9, in <module> import fcntl ImportError: No module named fcntl
然而我的服務器依舊是Windows版本,Flask服務器環境還是要搭建,那麽得采用什麽方案呢?
此處推薦采用tornado。
那麽什麽是tornado呢?
摘抄至網上一篇文章(http://www.tornadoweb.cn/)介紹:Tornado 是 FriendFeed 使用的可擴展的非阻塞式 web 服務器及其相關工具的開源版本。這個 Web 框架看起來有些像 web.py 或者 Google 的 webapp,不過為了能有效利用非阻塞式服務器環境,這個 Web 框架還包含了一些相關的有用工具 和優化。
Tornado 和現在的主流 Web 服務器框架(包括大多數 Python 的框架)有著明顯的區別:它是非阻塞式服務器,而且速度相當快。得利於其 非阻塞的方式和對 epoll 的運用,Tornado 每秒可以處理數以千計的連接,這意味著對於實時 Web 服務來說,Tornado 是一個理想的 Web 框架。我們開發這個 Web 服務器的主要目的就是為了處理 FriendFeed 的實時功能 ——在 FriendFeed 的應用裏每一個活動用戶都會保持著一個服務器連接。(關於如何擴容 服務器,以處理數以千計的客戶端的連接的問題,請參閱 C10K problem。)
至於具體怎麽運用,可以查看上面文章介紹,也可以參見下文的具體使用代碼。
2 具體實現
看到下面具體實現代碼,會讓大家感嘆,Python的確是一個優美的語言,Flask框架也的確是對應小而又輕量級的框架美稱呀。使用MongoDB數據庫,操作數據庫也變得極為簡單。
在看下面代碼之前,需要簡單說一下REST的基本思想原理,也相當於是我自己進一步加深印象吧。下面解釋應用自阮一峰博客的一個評論,我感覺這樣描述的很在理。
REST四個基本原則:
1.使用HTTP動詞:GET POST PUT DELETE;
2.無狀態連接,服務器端不應保存過多上下文狀態,即每個請求都是獨立的;
3.為每個資源設置URI;
4.通過XML JSON進行數據傳遞;
實現上述原則的架構即可稱為RESTFul架構。
1.互聯網環境下,任何應用的架構和API可以被快速理解;
2.分布式環境下,任何請求都可以被發送到任意服務器;
3.異構環境下,任何資源的訪問和使用方式都統一;
看到上面介紹,既然說了REST方式使用HTTP動詞GET POST PUT DELETE來實現相關操作。
那麽下面代碼就簡單實現一下這四個動詞的具體操作功能。
GET:實現從服務器後臺獲取數據功能,例如登陸接口功能實現;
POST:實現向服務器後臺提交數據功能,例如註冊接口功能實現;
PUT:實現修改服務器後臺已有數據功能;
DELETE:實現刪除服務器後臺已有數據功能。
看完上面介紹,下面就請看代碼:
如果不使用tornado,直接使用下面一個mongo.py文件中代碼即可實現本文標題所述功能:
#coding=utf-8 #mongo.py from flask import Flask,abort from flask import jsonify from flask import request from flask_pymongo import PyMongo app = Flask(__name__) app.config[‘MONGO_DBNAME‘] = ‘rest‘ app.config[‘MONGO_URI‘] = ‘mongodb://172.18.252.20:27017/rest‘ #如果部署在本上,其中ip地址可填127.0.0.1 mongo = PyMongo(app) @app.route(‘/login‘, methods=[‘GET‘]) def get_all_users(): star = mongo.db.userInfo.find() output = [] for s in star: output.append({‘name‘ : s[‘name‘], ‘pwd‘ : s[‘pwd‘]}) return jsonify({‘result‘ : output}) @app.route(‘/register‘, methods=[‘POST‘]) def add_user(): star = mongo.db.userInfo name = request.json[‘name‘] pwd = request.json[‘pwd‘] star_id = star.insert({‘name‘: name, ‘pwd‘: pwd}) new_star = star.find_one({‘_id‘: star_id }) output = {‘name‘ : new_star[‘name‘], ‘pwd‘ : new_star[‘pwd‘]} return jsonify({‘result‘ : output}) @app.route(‘/modify/<string:name>‘, methods=[‘PUT‘]) def update_user(name): user = mongo.db.userInfo.find({"name":name}) output = [] for s in user: output.append({‘name‘: s[‘name‘], ‘pwd‘: s[‘pwd‘]}) if len(output) == 0: abort(404) mongo.db.userInfo.update({"name":name},{‘$set‘:{"name":"LZ111"}}) return jsonify({‘result‘: output}) @app.route(‘/delete/<string:name>‘, methods=[‘DELETE‘]) def delete_user(name): user = mongo.db.userInfo.find({"name": name}) output = [] for s in user: output.append({‘name‘: s[‘name‘], ‘pwd‘: s[‘pwd‘]}) if len(output) == 0: abort(404) mongo.db.userInfo.remove({‘name‘: name}) return jsonify({‘result‘: True}) if __name__ == ‘__main__‘: # app.run(host = ‘0.0.0.0‘, port = 80, debug = True) app.run()
如果使用tornado,新建一個tornado_server.py文件,添加以下代碼,作為Flask服務啟動部署,也可以實現相關功能:
#coding=utf-8 #tornado_server.py from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from mongo import app http_server = HTTPServer(WSGIContainer(app)) # http_server.listen(9000) #此時,開啟端口9000,默認本機127.0.0.1的IP地址 http_server.bind(80, "172.18.252.20")# 開啟端口為9000,172.18.252.20為內網ip地址,也可以設置為0.0.0.0, http_server.start(1) IOLoop.instance().start()
看完上面代碼,點擊運行,即可實現相關接口功能了。既然是接口,GET方式還好說,如果是POST方式,使用瀏覽器就不那麽好操作了,此時我們需要使用一款接口測試軟件,在這裏我推薦使用Postman(PS:Postman百度經驗介紹,Postman官網下載鏈接),如果有同學使用基於Linux相關系統,推薦使用CURL來實現。
下面就正式開始使用Postman測試Get、Post、Put和Delete方式接口:
Get方式,選中下圖中下拉框GET方式,直接輸入URL,然後點擊Send藍色按鈕即可得到請求數據。
Post方式,選中下拉框中Post方式,這裏由於要發送數據,需要稍微設置一下。
首先,在下圖中Headers中要選擇Content-Type的數據方式,這裏我選擇的是json格式:
然後,點開下圖中Body,選擇raw,添加要存入的json格式數據,如下:
最後,點擊Send按鈕,在最下面出現相關提示信息後,即可查看Post請求結果。
Put方式操作和Get方式雷同,不同的是需要選中操作方式為Put,具體如下圖:
Delete方式和Put請求幾乎一樣,不同的是一個執行修改操作,一個執行刪除操作而已,具體如下圖:
基本操作就這樣,看完上面代碼,發現使用FLask+MongoDB寫後端接口是不是特別簡單?
參考資料:
1.Designing a RESTful API with Python and Flask(PS:附加一個中文版,不過裏面代碼有bug)
2.理解RESTful架構
3.MONGODB RESTFUL API WITH FLASK
使用Flask+MongoDB實現基於REST的接口簡單操作