2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】FirestoreのCRUD処理を行う Web API を Cloud Run Functions でさくっと実装

Posted at

目的

Webアプリのモックアップを開発する際にバックエンドとデータベースをさくっと手軽に用意したいと思ったので実装してみました。
Google Cloud Platform の無料枠を存分に使ってやりましょう💰

さくっと構築

image.png

GCPプロジェクト配下にFirestoreのデータベース&コレクションと Cloud Run Functions の関数(ランタイム: Python 3.12)を作成していきます。

たぶん5分あれば終わります。

Firestoreにデータベースを作成

モードはネイティブを選択してます。
データベースIDを (default) で作成すると無料枠の対象になるのでそのままにします。
なお今回はさくっと動作確認することが目的なので、セキュリティルールはテストルールです。

image.png

データベースが作成できたらコレクションと最初のドキュメントを作っておきます。

image.png

これにてFirestoreは準備完了。

image.png

Cloud Run Functions を作成

image.png

作成するコード

以下4つのメソッドを持つ関数を作成します。

メソッド CRUD 処理
POST Create リクエストされたJSONのキーと値を使ってドキュメントを作成。
GET Read コレクション直下のドキュメントを全件取得。
PUT Update リクエストされたJSONから id の値を取得し、該当するドキュメントを更新。
DELETE Delete リクエストされたJSONから id の値を取得し、該当するドキュメントを削除。
  • GCPプロジェクトのIDは意味のある情報か否かが紛らわしいと思ったのでマスクしました、読み替えてください
  • データベース名の指定が無いのは多分未指定だと (default) として扱われてるんじゃないかと思います(調べてないですごめんなさい)
  • コレクション名はこの手順で作成した myCollection を指定してるのでこれも適宜読み替えてください
main.py
import functions_framework
from flask import jsonify
from google.cloud import firestore
from werkzeug.exceptions import MethodNotAllowed

db_ref = firestore.Client(project='********')  # MASKED
collection_ref = db_ref.collection('myCollection')

@functions_framework.http
def api(request):
    """Firestore CRUD Function.
    """
    if request.method == 'POST':  # Create
        _, doc_ref = collection_ref.add(request.get_json())
        return jsonify({'id': doc_ref.id}), 201

    elif request.method == 'GET':  # Read
        docs = [{d.id: d.to_dict()} for d in collection_ref.stream()]
        return jsonify(docs)
    
    elif request.method == 'PUT':  # Update
        params = request.get_json()
        doc_id = params.pop('id')
        collection_ref.document(doc_id).update(params)
        return jsonify({}), 204
    
    elif request.method == 'DELETE':  # Delete
        collection_ref.document(request.get_json().get('id')).delete()
        return jsonify({}), 204

    # Other methods are not allowed
    return jsonify({'message': MethodNotAllowed.description}), MethodNotAllowed.code

今回は単一のエンドポイントでCRUD処理を実装することを目的としています。
実際のバックエンド開発の場面では PUTDELETE はパスで id を指定してリソースの階層と一致させたいところです。

requirements.txt
functions-framework==3.*
google-cloud-firestore

これをデプロイしたらシンプルなCRUD処理を行う Web API の完成です。

動作確認

  • リクエスト先はマスクしているので自身の Cloud Run Functions のURLを適用してください
  • パスの /api は関数のエントリポイントなのでこれも適宜変更

まずはCreateしてきます。

$ curl -X POST -H "Content-Type: application/json" -d '{"title":"foo"}' https://********.********.run.app/api
{"id":"nzNWqien4pzAjM72LY30"}

ちゃんと作成されていました。
リクエストパラメータやレスポンス( id )と一致してます。

image.png

次はRead。
これも上記のスクショと一致してるのでOK。

$ curl -X GET https://********.********.run.app/api
[{"FirstDoc":{"foobar":"bazqux"}},{"nzNWqien4pzAjM72LY30":{"title":"foo"}}]

3つめはUpdate。
Createで作成したドキュメントの title を更新します。

$ curl -X PUT -H "Content-Type: application/json" -d '{"id":"nzNWqien4pzAjM72LY30","title":"bar"}' https://********.********.run.app/api

ちゃんと更新されました。

image.png

最後はDelete。
作成、更新したドキュメントを削除します。

$ curl -X DELETE -H "Content-Type: application/json" -d '{"id":"nzNWqien4pzAjM72LY30"}' https://********.********.run.app/api

消えました。

image.png

おまけでそれ以外のメソッド。
ちゃんとエラーメッセージが応答してます。

$ curl -X OPTIONS https://********.********.run.app/api
{"message":"The method is not allowed for the requested URL."}

おしまい

触った所感、簡単なモックアップとか作るときにバックエンドとデータベースが必要な場面で力を発揮しそうです。無料枠で使えるし。

あと今回の実装の過程で google-cloud-firestore パッケージのソースコードを結構読み込んだので、コードリーディングと各クラスで使えるメソッドもそのうち記事にまとめようと思います。(「思います」なんで多分思うだけで終わります)

さいごに、画面キャプチャでGCPプロジェクトのIDが見えてたり関数のURLが見えてたりしてますが、この記事が世に出ることにはいずれも抹消しているのでマスクせず公開してます。
みなさん情報管理には十分気をつけてくださいね。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?