你好!在本系列的最後一個部分中,我們學習瞭如何建立基本的“ CRUD” 使用 python
list` 的 REST API 功能。但這不是現實世界應用程式的建構方式,因為如果您的伺服器重新啟動或上帝禁止崩潰,那麼您將丟失伺服器中儲存的所有資訊。為了解決這些問題(以及許多其他問題),使用了資料庫。所以,這就是我們要做的。我們將使用 MongoDB 作為我們的資料庫。
如果您剛從這部分開始,您可以在[此處]找到我們迄今為止編寫的所有程式碼(https://github.com/paurakhsharma/flask-rest-api-blog-series/tree/master/Part% 20 -%200)。
在開始之前,請確保您已在系統中安裝了 MongoDB。如果您還沒有安裝,可以安裝 Linux、[Windown](https://docs.mongodb.com/手冊/教學/install-mongodb-on-windows/)和[macOS](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/)。
主要有一些流行的函式庫可以讓 MongoDB 的使用變得更容易:
1) Pymongo 是 MongoDB 的低階 Python 包裝器,使用 Pymongo
類似於直接編寫 MongoDB 查詢。
以下是使用“Pymongo”更新“id”與給定“id”相符的電影名稱的簡單範例。
db['movies'].update({'_id': id},
{'$set': {'name': 'My new title'}})
Pymongo
不使用任何預先定義的模式,因此它可以充分利用 MongoDB 的無模式特性。
2) MongoEngine 是物件文件映射器,它使用文件模式,使 MongoDB 的使用變得清晰、更容易。
這是使用“mongoengine”的相同範例。
Movies.objects(id=id).update(name='My new title')
「Mongoengine」對資料庫中的欄位使用預先定義架構,這限制了它使用 MongoDB 的無架構性質。
正如我們所看到的,雙方都有各自的優點和缺點。因此,請選擇最適合您的專案的一種。在本系列中,我們將學習“Mongoengine”,如果您希望我也介紹“Pymongo”,請在下面的評論部分告訴我。
為了在我們的Flask
應用程式中更好地使用Mongoengine
,有一個很棒的Flask
擴展,名為[Flask-Mongengine](http://docs.mongoengine.org/projects/flask- mongoengine/en/latest/)。
那麼,讓我們開始安裝「flask-mongoengine」。
pipenv install flask-mongoengine
注意:由於flask-mongoengine
是在mongoengine
之上建造的,所以在安裝Flask-mongoengine 時會自動安裝,而且mongoengine
是在pymongo
之上建造的,所以它也會被安裝
現在,讓我們在「movie-bag」中建立一個新資料夾。我將其稱為“資料庫”。在「database」資料夾中建立一個名為「db.py」的檔案。另外,建立另一個檔案並將其命名為“models.py”
讓我們看看文件/資料夾現在是什麼樣子。
movie-bag
│ app.py
| Pipfile
| Pipfile.lock
└───database
│ db.py
└───models.py
現在,讓我們深入探討有趣的部分。
首先,讓我們透過將以下程式碼新增至「db.py」來初始化我們的資料庫
#~movie-bag/database/db.py
from flask_mongoengine import MongoEngine
db = MongoEngine()
def initialize_db(app):
db.init_app(app)
在這裡,我們導入了“MongoEngine”並建立了“db”物件,並定義了一個函數“initialize_db()”,我們將從“app.py”中呼叫該函數來初始化資料庫。
讓我們在“models”目錄中的“movie.py”中編寫以下程式碼
#~movie-bag/database/models.py
from .db import db
class Movie(db.Document):
name = db.StringField(required=True, unique=True)
casts = db.ListField(db.StringField(), required=True)
genres = db.ListField(db.StringField(), required=True)
我們剛剛建立的是資料庫的文件。因此,使用者無法新增此處定義的其他欄位。
這裡我們可以看到「Movie」文件有三個欄位:
1)name
:是一個String
類型的字段,我們在這個字段上也有兩個約束。
- “必需”,這意味著用戶在不提供標題的情況下無法建立新電影。
- “唯一”,這意味著電影名稱必須是唯一的,不能重複。
2) casts
:是一個list
類型的字段,其中包含String
類型的值
3) genres
: 與casts
相同
最後,我們可以在「app.py」中初始化資料庫,並更改「view」函數(處理 API 請求的函數)以使用我們先前定義的「Movie」文件。
#~movie-bag/app.py
-from flask import Flask, jsonify, request
+from flask import Flask, request, Response
+from database.db import initialize_db
+from database.models import Movie
app = Flask(__name__)
-movies = [
- {
- "name": "The Shawshank Redemption",
- "casts": ["Tim Robbins", "Morgan Freeman", "Bob Gunton", "William Sadler"],
- "genres": ["Drama"]
- },
- {
- "name": "The Godfather ",
- "casts": ["Marlon Brando", "Al Pacino", "James Caan", "Diane Keaton"],
- "genres": ["Crime", "Drama"]
- }
-]
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/movie-bag'
+}
+
+initialize_db(app)
[email protected]('/movies')
-def hello():
- return jsonify(movies)
[email protected]('/movies')
+def get_movies():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
[email protected]('/movies', methods=['POST'])
-def add_movie():
- movie = request.get_json()
- movies.append(movie)
- return {'id': len(movies)}, 200
[email protected]('/movies', methods=['POST'])
+ body = request.get_json()
+ movie = Movie(**body).save()
+ id = movie.id
+ return {'id': str(id)}, 200
[email protected]('/movies/<int:index>', methods=['PUT'])
-def update_movie(index):
- movie = request.get_json()
- movies[index] = movie
- return jsonify(movies[index]), 200
[email protected]('/movies/<id>', methods=['PUT'])
+def update_movie(id):
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
[email protected]('/movies/<int:index>', methods=['DELETE'])
-def delete_movie(index):
- movies.pop(index)
- return 'None', 200
[email protected]('/movies/<id>', methods=['DELETE'])
+def delete_movie(id):
+ Movie.objects.get(id=id).delete()
+ return '', 200
app.run()
哇!變化很多,讓我們一步一步地進行變化。
-from flask import Flask, jsonify, request
+from flask import Flask, request, Response
+from database.db import initialize_db
+from database.models.movie import Movie
這裡我們刪除了“jsonify”,因為我們不再需要,並加入了“Response”,我們用它來設定回應的類型。然後我們從之前定義的「db.py」導入「initialize_db」來初始化資料庫。最後,我們從“movie.py”導入“Movie”文件
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/movie-bag'
+}
+
+db = initialize_db(app)
這裡我們設定 mongodb 資料庫的配置。這裡主機的格式為「<host-url>/<database-name>」。由於我們已經在本地安裝了 mongodb,因此我們可以從“mongodb://localhost/”存取它,並且我們將資料庫命名為“movie-bag”。
最後,我們初始化資料庫。
[email protected]('/movies')
+def get_movies():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
在這裡,我們使用“Movies.objects()”從“Movie”文件中獲取所有物件,並使用“to_json()”將它們轉換為“JSON”。最後,我們傳回一個「Response」物件,其中我們將回應類型定義為「application/json」。
[email protected]('/movies', methods=['POST'])
+ body = request.get_json()
+ movie = Movie(**body).save()
+ id = movie.id
+ return {'id': str(id)}, 200
在「POST」請求中,我們首先取得發送的「JSON」和一個請求。然後我們使用“Movie(body)”請求中的欄位來載入“Movie”文件。這裡的「」稱為擴充運算符,在 JavaScript 中寫為「...」(如果您熟悉的話)。顧名思義,它的作用是傳播「dict」物件。 <br/>
所以,Movie(**body)
變成了
Movie(name="Name of the movie",
casts=["a caste"],
genres=["a genre"])
最後,我們保存文件並獲取其“id”,我們將其作為回應返回。
[email protected]('/movies/<id>', methods=['PUT'])
+def update_movie(id):
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
這裡我們先找到與請求中發送的「id」相符的Movie文件,然後更新它。這裡我們也應用了擴充運算子將值傳遞給「update()」函數。
[email protected]('/movies/<id>', methods=['DELETE'])
+def delete_movie(id):
+ Movie.objects.get(id=id).delete()
+ return '', 200
與此處的“update_movie()”類似,我們獲取與給定“id”匹配的電影文件並將其從資料庫中刪除。
哦,我剛剛想起來,我們還沒有將 API 端點加入到“GET”,僅從我們的伺服器獲取一個文件。
讓我們加入它:
在 app.run()
上方加入以下程式碼
@app.route('/movies/<id>')
def get_movie(id):
movies = Movie.objects.get(id=id).to_json()
return Response(movies, mimetype="application/json", status=200)
現在您可以從 API 端點「/movies/<valid_id>」取得單一影片。
要執行伺服器,請確保您位於“movie-bag”目錄。
然後執行
pipenv shell
python app.py
在終端機中啟動虛擬環境並啟動伺服器。
哇!恭喜您已經走到這一步了。要測試API,請使用我們在上一篇 中使用的“ Postman」本系列的一部分。
您可能已經注意到,如果我們向端點發送無效資料,例如:沒有名稱或其他字段,我們會收到“HTML”形式的不友善錯誤。如果我們嘗試取得資料庫中不存在的「id」影片文件,那麼我們也會收到「HTML」回應形式的不友善錯誤。這並不是一個精心建構的 API 的例外行為。我們將在本系列的後面部分中了解如何處理此類錯誤。
Pymongo
和 Mongoengine
之間的差異。
如何使用「Mongoengine」建立文件架構。
如何使用「Mongoengine」執行「CRUD」操作。
Python 擴充運算子。
您可以在[此處]找到這部分的完整程式碼(https://github.com/paurakhsharma/flask-rest-api-blog-series/tree/master/Part%20-%201)
在下一部分中,我們將學習如何使用「Blueprint」來更好地建立 Flask 應用程式。以及如何使用“flask-restful”以最少的設定遵循最佳實踐,更快地建立 REST API
直到那時快樂編碼😊
原文出處:https://dev.to/paurakhsharma/flask-rest-api-part-1-using-mongodb-with-flask-3g7d