Flask, DynamoDB, Lambdaを使用したCRUDアプリケーションの作成 #
このチュートリアルでは、Flask、DynamoDB、およびAWS Lambdaを使用して、CRUD(Create, Read, Update, and Delete)機能を持つ簡単なウェブアプリケーションを作成します。これらのテクノロジーを組み合わせることで、スケーラブルで効率的なサーバーレスアーキテクチャを実現できます。
必要な環境 #
- Python 3.8+
- AWSアカウント
- pip
- Virtualenv (オプション)
ステップ1: プロジェクトのセットアップ #
- プロジェクトディレクトリを作成し、移動します。
mkdir flask-dynamodb-crud
cd flask-dynamodb-crud
仮想環境を作成し、アクティベートします。
python -m venv venv
source venv/bin/activate
必要なパッケージをインストールします。
pip install flask boto3 zappa
ステップ2: Flaskアプリケーションの作成 #
- プロジェクトディレクトリ内で、app.pyという名前のファイルを作成し、以下のコードを追加します。
from flask import Flask, render_template, request, redirect, url_for
import boto3
app = Flask(__name__)
@app.route('/')
def home():
return "Hello, Flask DynamoDB CRUD!"
if __name__ == '__main__':
app.run(debug=True)
アプリケーションを実行して、ローカル環境で動作することを確認します。
python app.py
ステップ3: DynamoDBテーブルの作成 #
AWS管理コンソールにログインし、DynamoDBサービスに移動します。 「テーブルの作成」をクリックし、以下の設定でテーブルを作成します。
- テーブル名: todos
- パーティションキー: id (文字列)
テーブルが作成されるのを待ちます。
ステップ4: Boto3を使ったDynamoDBへのアクセス #
app.pyに以下のコードを追加し、DynamoDBに接続します。
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('todos')
ステップ5: CRUD機能の実装 #
create機能とread機能をまずは作成します。
from flask import Flask, render_template, request, redirect, url_for
import boto3
app = Flask(__name__)
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('todos')
# Home
@app.route('/')
def home():
#return "Hello, Flask DynamoDB CRUD!"
response = table.scan()
items = response['Items']
return render_template('index.html', items=items)
# Create GET
@app.route('/create', methods=['GET'])
def create_form():
return render_template('create.html')
# Create POST
@app.route('/create', methods=['POST'])
def create():
item = {
'id': request.form['id'],
'task': request.form['task'],
'status': request.form['status']
}
table.put_item(Item=item)
return redirect(url_for('home'))
# Read Single
@app.route('/read/<string:id>', methods=['GET'])
def read(id):
response = table.get_item(Key={'id': id})
return render_template('read.html', item=response['Item'])
if __name__ == '__main__':
app.run(debug=True)
必要なライブラリをインポートします。
- Flask, render_template, request, redirect, url_for: Flaskフレームワークで使用される関数やクラスを提供します。
- boto3: AWSのサービスとやり取りするためのPythonライブラリです。
Flaskアプリケーションインスタンスを作成し、DynamoDBリソースと’todos’という名前のテーブルを定義します。
- ホームルート('/'): このルートは、DynamoDBテーブルからすべてのアイテムを取得し、それらをHTMLテンプレート(index.html)に表示します。
- タスク作成フォームルート('/create'、GETリクエスト): このルートは、タスクを作成するためのHTMLフォーム(create.html)を表示します。
- タスク作成ルート('/create'、POSTリクエスト): このルートは、フォームから送信されたデータを使用して、新しいタスクをDynamoDBテーブルに追加し、その後、ホームルートにリダイレクトします。
- タスク詳細表示ルート('/read/string:id'、GETリクエスト): このルートは、指定されたIDを持つタスクをDynamoDBから取得し、その詳細をHTMLテンプレート(read.html)に表示します。
最後に、if __name__ == '__main__':
でアプリケーションが直接実行されている場合、デバッグモードでアプリケーションを起動します。
このコードでは、タスクの更新と削除機能が実装されていません。機能を追加することで、完全なCRUDアプリケーションになります。
ステップ6: テンプレートの作成 #
templatesディレクトリを作成し、index.html
,create.html
,read.html
を作成します。
[index.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo List</title>
</head>
<body>
<h1>Todo List</h1>
<ul>
{% for item in items %}
<li>
<a href="{{ url_for('read', id=item.id) }}">{{ item.task }}</a>
</li>
{% endfor %}
</ul>
<a href="{{ url_for('create') }}">Create a new Todo</a>
</body>
</html>
[create.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create Todo</title>
</head>
<body>
<h1>Create a new Todo</h1>
<form action="{{ url_for('create') }}" method="post">
<label for="id">ID:</label>
<input type="text" name="id" required>
<label for="task">Task:</label>
<input type="text" name="task" required>
<label for="status">Status:</label>
<select name="status">
<option value="not started">Not started</option>
<option value="in progress">In progress</option>
<option value="completed">Completed</option>
</select>
<button type="submit">Create</button>
</form>
<a href="{{ url_for('home') }}">Back to Home</a>
</body>
</html>
[read.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo</title>
</head>
<body>
<h1>{{ item.task }}</h1>
<p>Status: {{ item.status }}</p>
<a href="{{ url_for('home') }}">Back to Home</a>
</body>
</html>
ステップ7: Zappaを使ってAWS Lambdaにデプロイ #
Zappaの設定ファイルzappa_settings.jsonを作成します。
{
"production": {
"app_function": "app.app",
"aws_region": "ap-northeast-1",
"profile_name": "default",
"project_name": "flask-dynamodb-crud",
"runtime": "python3.8",
"s3_bucket": "your-s3-bucket-name"
}
}
Zappaを使ってデプロイします。
zappa deploy production
デプロイが完了したら、表示されるURLにアクセスしてアプリケーションが正常に動作していることを確認します。
ステップ8: Crudの更新と削除を追加する。 #
テンプレートを作成します。
[update.html]
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Update Todo</title>
</head>
<body>
<h1>Update Todo</h1>
<form action="{{ url_for('update', id=item.id) }}" method="post">
<input type="hidden" name="_method" value="PUT">
<label for="task">Task:</label>
<input type="text" name="task" value="{{ item.task }}" required>
<label for="status">Status:</label>
<select name="status">
<option value="not started" {% if item.status == 'not started' %}selected{% endif %}>Not started</option>
<option value="in progress" {% if item.status == 'in progress' %}selected{% endif %}>In progress</option>
<option value="completed" {% if item.status == 'completed' %}selected{% endif %}>Completed</option>
</select>
<button type="submit">Update</button>
</form>
<a href="{{ url_for('read', id=item.id) }}">Cancel</a>
</body>
</html>
[delete.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Delete Todo</title>
</head>
<body>
<h1>Delete Todo</h1>
<p>Are you sure you want to delete "{{ item.task }}"?</p>
<form action="{{ url_for('delete', id=item.id) }}" method="post">
<input type="hidden" name="_method" value="DELETE">
<button type="submit">Yes, delete it</button>
</form>
<a href="{{ url_for('read', id=item.id) }}">Cancel</a>
</body>
</html>
[app.py]
# Update POST
@app.route('/update/<string:id>', methods=['POST'])
def update(id):
task = request.form['task']
status_alias = request.form['status']
response = table.update_item(
Key={'id': id},
UpdateExpression="set task=:t, #status_alias=:s",
ExpressionAttributeValues={
':t': task,
':s': status_alias
},
ExpressionAttributeNames={
"#status_alias": "status"
},
ReturnValues="UPDATED_NEW"
)
return redirect(url_for('read', id=id))
# Delete POST
@app.route('/delete/<string:id>', methods=['POST'])
def delete(id):
table.delete_item(Key={'id': id})
return redirect(url_for('home'))
# update GET
@app.route('/update/<string:id>', methods=['GET'])
def update_form(id):
response = table.get_item(Key={'id': id})
return render_template('update.html', item=response['Item'])
# delete GET
@app.route('/delete/<string:id>', methods=['GET'])
def delete_form(id):
response = table.get_item(Key={'id': id})
return render_template('delete.html', item=response['Item'])
タスク更新ルート('/update/string:id'、POSTリクエスト): このルートは、フォームから送信されたデータを使用して、指定されたIDのタスクをDynamoDBテーブルで更新し、その後、更新されたタスクの詳細ページにリダイレクトします。
- update_itemメソッドを使用して、DynamoDBテーブルのアイテムを更新します。
- UpdateExpressionにより、タスクとステータスの属性を更新します。
- ExpressionAttributeValuesにより、更新される値を設定します。
- ExpressionAttributeNamesにより、予約語として使用できない属性名(この場合は’status')をエイリアスとして設定します。
タスク削除ルート('/delete/string:id'、POSTリクエスト): このルートは、指定されたIDのタスクをDynamoDBテーブルから削除し、その後、ホームルートにリダイレクトします。
- delete_itemメソッドを使用して、DynamoDBテーブルからアイテムを削除します。
タスク更新フォームルート('/update/string:id'、GETリクエスト): このルートは、指定されたIDのタスクの情報をもとに、タスクを更新するためのHTMLフォーム(update.html)を表示します。
- get_itemメソッドを使用して、DynamoDBテーブルからアイテムを取得します。
タスク削除確認フォームルート('/delete/string:id'、GETリクエスト): このルートは、指定されたIDのタスクの情報をもとに、タスクを削除する前に確認を行うHTMLフォーム(delete.html)を表示します。
- get_itemメソッドを使用して、DynamoDBテーブルからアイテムを取得します。
ステップ9: Zappaで更新する #
Lambda関数を更新します。
$ zappa update production
ステップ10: クリーンアップ #
- Zappaを使ってアプリケーションを削除します。
$ zappa undeploy production
- AWS管理コンソールからDynamoDBテーブルtodosを削除します
まとめ #
これで、Flask, DynamoDB, Lambda, Zappaを使ったCRUDアプリケーションの作成とデプロイが完了しました。これをベースにして、アプリケーションをカスタマイズし、さらに多機能なWebアプリケーションを作成することができます。例えば、認証機能を追加してユーザーがログインできるようにする、複数のテーブルやリレーションを持つデータモデルを実装する、フロントエンドフレームワークを利用してUIを向上させるなどが考えられます。
このチュートリアルでは、サーバーレスアーキテクチャを利用して低コストでスケーラブルなWebアプリケーションを作成する方法を学びました。