FlaskでREST APIのサンプルアプリの作り方|sqlalchemyを使った方法を解説

スポンサーリンク

この記事では、APIとREST APIに慣れ親しみ、その後、独自のFlask REST APIアプリケーションを構築していきます。

スポンサーリンク

APIとは?

API (Application Programming Interface) は、異なるアプリケーションと対話するためのインターフェイスを提供します。

APIを使用すると、他のアプリケーションからデータ – 値を取得したり、処理したり、送信したりすることができます

例えば、Webアプリケーションを考えてみましょう。

クライアントがあるデータをリクエストとして送信すると、サーバーはそれを処理し、適切なレスポンスデータをクライアントに送り返します。

この一連のやり取りは、APIを介して行われます。

では、この例をもう一度見て、APIの役割がどこにあるのかを見てみましょう。

したがって、クライアントがサーバーに送るのは、リクエストデータを含むAPIです。

サーバーはそれを処理し、適切なレスポンスデータを含む別のAPIをクライアントに送り返す。

CRUD演算子とHTTPメソッド

APIを使用する際、クライアントはさまざまな方法でサーバーにリクエストデータを送信することができます

これらのタイプは、CRUD操作と呼ばれます。

各CRUD(Create Retrieve Update Delete)演算子には、それに関連するHTTPメソッドがあります。

それでは、それらについて見ていきましょう。

  • GET HTTPメソッド-サーバーから特定の情報(表示目的)を取得します。
  • POST – サーバーデータベースに新しい情報を送信/作成します。
  • PUT – データベース内の情報を編集/更新するか、まだ存在しない場合はそれを追加します。
  • DELETE – サーバーデータベースから情報を削除します。

さて、メソッドがわかったところで、それぞれのメソッドをいつ使うかを理解しましょう。

次のような例を考えてみましょう。

名前、クラス、年齢などの情報を含む学生データベースがあります。

  • 生徒のリストを見るには – GET HTTP メソッドを使用します。
  • 新しい学生情報を追加するには – POST HTTPメソッドを使用してください。
  • 生徒の特定の情報(クラス/年齢)を編集するには – PUT HTTPメソッドを使用してください。
  • データベースから生徒の情報を削除するには、DELETE HTTP メソッドを使用します。

REST API とは何ですか?

REST (Representational State Transfer) APIは、標準的なAPIと似ています。

ここで、サーバーにリクエストを送ると、データで応答するAPIとは異なり、REST APIはリソースで応答します。

REST API のリソース

さて、リソースとは何でしょうか?

まあ、リソースはデータなんだけど、見方が変わる。

リソースは、オブジェクト指向プログラミングに似ています。

以下の例で理解しましょう。

Flask のビュー、”/Book/Book123″ を考えてみましょう。

ここで、同じView Endpointで4つのアクションを実行することができます

  • GET Book/Book123: Book123 “の情報を表示します。
  • POST Book/Book123: 新しい本 “Book123” を作成します。
  • PUT Book/Book123: ブック “Book123 “の情報を更新/編集します。
  • DELETE Book/Book123: ブック “Book123 “の情報を更新/編集します。データベースから “Book123 “を削除します。

1つの実体が複数の機能(OOPメソッド)を持つので、Bookリソースと考えることができる。

したがって、ClientとServerの間のやりとりは、個々のエンドポイントリクエストではなく、リソース(異なるアクションのための同じエンドポイントを持つ)です。

REST APIのステートレス化

REST APIのもう一つの特徴は、ステートレスであることです。

これはどういうことかというと、サーバーが1つのアクションを完了した後、そのことを忘れてしまうということです。

これを例で理解しましょう。

上で見たBook Resourceを考えてみましょう。

Stephen Hawkings の ” A Brief History Of Time ” という本に関するデータを POST メソッドで送信したとします。

サーバーはこの情報をデータベースに追加し、そのアクションを忘れます。

次に私が GET リクエストでその本を取得するとき、サーバは前回の POST メソッドの動作を全く覚えていないことになります。

サーバーはまずデータベースにアクセスし、Bookを探します。

そして、Bookを見つけたら、そのデータで応答します。

そして、アクションを完了した後は、そのことを忘れます。

クライアントとサーバーのAPIインタラクションにおけるJSONの使用

APIは、リクエストの受け付けと返信にJSON形式を使用します。

つまり、クライアントはリクエストデータをJSONテキストとしてサーバーに送信します。

同様に、サーバーはそのデータを処理し、再びJSONテキストとして応答を返します。

従って、REST APIを利用したWebアプリケーションの全体の流れは、以下のようになります。

  • ユーザーはリクエストデータをJSONとしてサーバーに送信します。
  • サーバーは、まずJSONをPythonで読める形式に変換します。
  • サーバーはまずJSONをpythonで読める形式に変換します。
  • そして、WebページのTemplateがJSONのレスポンスをユーザーが読める形式に変換し、Webページに表示します。

このように、APIにおけるクライアント側(FRONT-END)とサーバー側(BACK-END)の実際の情報のやりとりは、JSONテキストを使って行われます。

JSON形式は、Pythonの辞書に似ています。

{
    'student1':{
        'name':'XYZ',
        'age' : 21
    }
}

POSTMANのインストール

Postman は API 開発のためのコラボレーションプラットフォームです。

Postmanの機能はAPI構築の各ステップを簡素化し、コラボレーションを効率化するので、より良いAPIをより早く作成することができます

POSTMANをダウンロードするには、ここをクリックしてください。

インストールすると、以下のようになります。

pip install flask_restful

さて、コーダーの皆さん! それでは、REST APIの構築を始めましょう。

Flask REST API アプリケーションの構築

このセクションでは、Flask の RESTFul ライブラリを使用して、シンプルな Book REST API アプリケーションを構築します。

1. Flask_Restful のシステムへのインストール

FlaskのRestFullパッケージをインストールするために、pipコマンドを実行します。

pip install flask_sqlalchemy

これでインストールが完了したので、次はデータベース編です。

2. SQLAlchemy を使った DB モデルのコード化

ここでは、モデルを格納するために SQLite データベースを使用します。

使用するには、まず flask_sqlalchemy をインストールします。

from flask_sqlalchemy import SQLAlchemy
 
db = SQLAlchemy()
 
class BookModel(db.Model):
    __tablename__ = 'books'
 
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    price = db.Column(db.Integer())
    author = db.Column(db.String(80))
 
    def __init__(self, name, price, author):
        self.name = name
        self.price = price
        self.author = author
     
    def json(self):
        return {"name":self.name, "price":self.price, "author":self.author}

models.py ファイルを作成し、以下のコードを追加します。

from flask import Flask
from flask_restful import Api
 
app = Flask(__name__)
 
api = Api(app) #Flask REST Api code
 
if __name__ == '__main__':
    app.run(host='localhost', port=5000)

ここでは、BookModelにname、price、authorのフィールドを追加しています。

APIはJSONなので、JSONのブックオブジェクトを返すために、Objectメソッド.json()を作成します。

まず、DBモデルを作成するために、DBインスタンスをインスタンス化する必要があります。

SQLAlchemy について疑問があれば、 SQLAlchemy チュートリアルを参照してください。

さて、モデルができたので、Flaskアプリケーションのメインコードを書いてみましょう。

3. Flask アプリケーションのコード化

Flask REST API では、Flask に REST API の Web アプリであることを示すために、API(app) インスタンスを追加する必要があります。

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///<db_name>.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
 
db.init_app(app)

次に、SQLAlchemy に SQLite の情報を与えて、DB インスタンス(フォーム models.py)をこのアプリケーションファイルにリンクさせる必要があります。

そのために、次のコードを追加します。

@app.before_first_request
def create_table():
    db.create_all()

ここで、 を任意の DB 名に置き換えてください。

SQLALCHEMY_TRACK_MODIFICATIONSは、シンプルにするためにFalseのままです。

3行目は、DBインスタンスとアプリをリンクしています。

ウェブページのユーザーが使用できるように、DBファイルを配置する必要があります。

また、最初のユーザー・リクエストの前にも必要です。

そこで、ファイルを作成するために、この関数を使用します。

class BooksList(Resource):
    def get(self):
        #get all objects from BookModel
        #return the JSON text of all objects
        pass
         
    def post(self):
        #convert the JSON data sent by the user to python-format
        #create a new bookModel object and send in the data
        #save to DB
        pass

これを上記のコードの下に追加してください。

さて、これでFlask REST API Resource Classesのコーディングができました。

4. 書籍リストリソースを追加する

このリソースは以下のようなものです。

  • GETメソッド:DBに登録されている書籍の一覧を表示します。
  • POSTメソッド : 新しい書籍情報をDBに追加する

というわけで、コードは以下のようになります。

class BooksList(Resource):
    def get(self):
        books = BookModel.query.all()
        return {'Books':list(x.json() for x in books)}
 
    def post(self):
        data = request.get_json()
        new_book = BookModel(data['name'],data['price'],data['author'])
        db.session.add(new_book)
        db.session.commit()
        return new_book.json(),201

というわけで、上に書いたようなタスクができるコードになるはずです。

では、コメントを実際のコードに置き換えてみましょう。

api.add_resource(BooksView, '/books')

ここでは、GETメソッドを使用しています。

  • BookModle.query.all()を使ってDBに存在する本を取得します。
  • 本のJSONテキストを1つずつリストで表示します。

POSTメソッドでは

  • request.get_json()を使ってJSONデータを変換します。
  • 新しいBookの情報を作成し、DBに追加します。

以上、最後にBooksList ResourceのURLエンドポイントを記載します。

class Book(Resource):
    def get(self,name):
        #get the book with the name given by the user
        #if book exists, return it else return 404 not found
 
    def put(self,name):
        #convert the JSON data sent by the user to python-format
        #Search if the book exists
        #if it exists, update it with the data given by the user
        #if does not exists, create and add the book into DB
 
    def delete(self,name):
        #Search if the book exists in the DB
        #delete it

5. 本のリソースを追加する

では、次のようなリソースを作成します。

  • GETメソッド。GETメソッド: ユーザーがリクエストした特定の本だけを表示する
  • PUTメソッド。PUTメソッド:特定の書籍の情報を編集します。存在しない場合は、作成する
  • DELETE メソッド。特定のブックを削除する

ここでは、以下のようなコードになります。

class Book(Resource):
    def get(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            return book.json()
        return {'message':'book not found'},404
 
    def put(self,name):
        data = request.get_json()
 
        book = BookModel.query.filter_by(name=name).first()
 
        if book:
            book.price = data["price"]
            book.author = data["author"]
        else:
            book = BookModel(name=name,**data)
 
        db.session.add(book)
        db.session.commit()
 
        return book.json()
 
    def delete(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            db.session.delete(book)
            db.session.commit()
            return {'message':'Deleted'}
        else:
            return {'message': 'book not found'},404

このコードは、上記のすべてのタスクを実行できるようにする必要があります。

そこで、コードを追加します。

api.add_resource(BookView,'/book/<string:name>')

GET メソッドの中で

  • BookModel.query.filter_by(name=name).first() は、DBから取得した最初の本を返します。その名前を持つものが見つからなかった場合は None を返します。
  • 見つかった場合は、本のJSONテキストを返します。さもなくば404を返す。

PUTメソッドの場合。

  • request.get_json()でJSONデータを変換します。
  • その名前の本を検索します。
  • 存在する場合は、古いデータを新しく送信されたデータで置き換える。
  • さもなければ、新しいBookオブジェクトを作成する
  • DBに追加する

DELETEメソッドでは

  • ユーザが指定した名前の本を取得します。
  • それを削除する

これで終わりです。

最後に、このResourceのURLエンドポイントを追加します。

from flask import Flask,request
from flask_restful import Api, Resource, reqparse
from models import db, BookModel
 
app = Flask(__name__)
 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
 
api = Api(app)
db.init_app(app)
 
@app.before_first_request
def create_table():
    db.create_all()
 
 
class BooksView(Resource):
    '''
    parser = reqparse.RequestParser()
    parser.add_argument('name',
        type=str,
        required=True,
        help = "Can't leave blank"
    )
    parser.add_argument('price',
        type=float,
        required=True,
        help = "Can't leave blank"
    )
    parser.add_argument('author',
        type=str,
        required=True,
        help = "Can't leave blank"
    )'''
 
    def get(self):
        books = BookModel.query.all()
        return {'Books':list(x.json() for x in books)}
 
    def post(self):
        data = request.get_json()
        #data = BooksView.parser.parse_args()
 
        new_book = BookModel(data['name'],data['price'],data['author'])
        db.session.add(new_book)
        db.session.commit()
        return new_book.json(),201
 
 
class BookView(Resource):
    '''
    parser = reqparse.RequestParser()
    parser.add_argument('price',
        type=float,
        required=True,
        help = "Can't leave blank"
        )
    parser.add_argument('author',
        type=str,
        required=True,
        help = "Can't leave blank"
        )'''
 
    def get(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            return book.json()
        return {'message':'book not found'},404
 
    def put(self,name):
        data = request.get_json()
        #data = BookView.parser.parse_args()
 
        book = BookModel.query.filter_by(name=name).first()
 
        if book:
            book.price = data["price"]
            book.author = data["author"]
        else:
            book = BookModel(name=name,**data)
 
        db.session.add(book)
        db.session.commit()
 
        return book.json()
 
    def delete(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            db.session.delete(book)
            db.session.commit()
            return {'message':'Deleted'}
        else:
            return {'message': 'book not found'},404
 
api.add_resource(BooksView, '/books')
api.add_resource(BookView,'/book/<string:name>')
 
app.debug = True
if __name__ == '__main__':
    app.run(host='localhost', port=5000)

これで完了です!

Flask Rest API アプリケーションの最終コード

というわけで、Flaskのメインアプリケーションを組み合わせたものは以下のようになります。

from flask_sqlalchemy import SQLAlchemy
 
db = SQLAlchemy()
 
class BookModel(db.Model):
    __tablename__ = 'books'
 
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    price = db.Column(db.Integer())
    author = db.Column(db.String(80))
 
    def __init__(self, name, price, author):
        self.name = name
        self.price = price
        self.author = author
     
    def json(self):
        return {"name":self.name, "price":self.price, "author":self.author}

models.py ファイルです。

{
    "name":"book1",
    "price":123,
    "author":"author1"
}

それでは、POSTMANを使ってサーバを起動し、確認してみましょう。

POSTMANを使ったFlask REST APIアプリケーションの実装

サーバーを起動し、POSTMANにアクセスします。

1. BooksList リソース:POST メソッド

POSTメソッドで”/books “エンドポイントに移動します。

ボディでraw – JSONを選択し、JSONデータをボディに追加します。

{
    "price": 100,
    "author":"author123"
}

送信

POSTMAN Window
POSTMAN Window

Book – book1が作成されます。

2. BooksList リソース:POST メソッド

GETメソッドで “books/”にアクセスし、送信を押してください。

DBに登録されている書籍の一覧が表示されます。

POST
POST

book1しかないので、リストに表示されているのは1件だけです。

3. 書籍のリソース:GETメソッド

GETメソッドで”/books/book1 “にアクセスし、送信をクリックします。

GET
GET

Book1の情報が表示されます。

4. 書籍資源:PUTメソッド

PUTメソッドで”/books/book1 “にアクセスし、本文に以下のJSONを追加してください。

GET
GET

名前はすでにURLリクエストで送信されているので、価格と著者のJSONを送信する必要があります。

送信を実行

PUT
PUT

価格と著者の値が変更されました。

GETメソッドでも確認してみてください。

5. 書籍資源:DELETEメソッド

DELETEメソッドで「/books/book1」に移動します。

DELETE
DELETE

削除されたことを確認

まとめ

以上です。

Flask REST APIフレームワークについて、十分な知識を得ることができたのではないでしょうか。

より深く理解するために、上記のコードを自分で試してみてください。

それではまた次回!

タイトルとURLをコピーしました