1. 程式人生 > >使用Flask+MongoDB實現基於REST的接口簡單操作

使用Flask+MongoDB實現基於REST的接口簡單操作

服務器環境 互聯 utf 遇到的問題 like .exe 查找 提示信息 進入

目錄

前言

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的接口簡單操作