Django REST Frameworkでdynamodbを操作するREST APIを作成する
はじめに
django REST Frameworkとboto3でAWSのDynamoDBに対して操作を行うapiを作成する。
GET、POST、PUT、DELETEの操作ができるようにする。
Dynamodbテーブル作成(事前準備)
下記のようなテーブルを事前に用意し、いくつかデータを入れておく
テーブル名: Fruits
hash key: Name
djangoプロジェクトの作成
django project(dynamo_operation)とapp(api)を作成
$ django-admin startproject dynamo_operation
$ cd dynamo_operation/
$ django-admin startapp api
setting.pyの編集
setting.py
にrest_framework
と先ほど作成したapp
のconfigを追加する。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', #追加
'api.apps.ApiConfig', #追加
]
DynamoDBリクエスト用のmodelを作成
djangoではDBの作成、操作にmodel
を用意する。
DynamoDBへのリクエストはboto3を使用するので特にmodel
は必要ないが、今回はmodel(dynamo_model.py)
を用意した。
class Fruit():
def __init__(self, name):
self.name = name
views.pyの編集
api/views.py
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from api.dynamo_models import Fruit
from boto3 import client
dynamodb_client = client('dynamodb')
class DynamoRequest(APIView):
# 全体GET
def get(self, request):
response = []
items = dynamodb_client.scan(TableName='Fruits')['Items']
for item in items:
fruit = Fruit(item['Name']['S'])
fruit.price = item.get('Price',{}).get('N', '')
response.append(fruit.__dict__)
return Response(response)
def post(self, request):
request_data = request.data
item = {'Name': {'S': request_data['Name']}}
if 'Price' in request_data:
item['Price'] = {'N': request_data['Price']}
dynamodb_client.put_item(
TableName = 'Fruits',
Item = item
)
return Response(status=status.HTTP_201_CREATED)
class DynamoDetailRequest(APIView):
#単体GET
def get(self, request, pk):
item = dynamodb_client.get_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)['Item']
fruit = Fruit(item['Name']['S'])
fruit.price = item.get('Price',{}).get('N', '')
return Response(fruit.__dict__)
def put(self, request, pk):
request_data = request.data
item = dynamodb_client.get_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)['Item']
price = item.get('Price',{}).get('N', '0')
if 'Price' in request_data:
price = request_data['Price']
dynamodb_client.put_item(
TableName = 'Fruits',
Item = {
'Name': {'S': item['Name']['S']},
'Price': {'N': price}
}
)
return Response(status=status.HTTP_200_OK)
def delete(self, request, pk):
dynamodb_client.delete_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)
return Response(status=status.HTTP_204_NO_CONTENT)
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from api.dynamo_models import Fruit
from boto3 import client
dynamodb_client = client('dynamodb')
class DynamoRequest(APIView):
# 全体GET
def get(self, request):
response = []
items = dynamodb_client.scan(TableName='Fruits')['Items']
for item in items:
fruit = Fruit(item['Name']['S'])
fruit.price = item.get('Price',{}).get('N', '')
response.append(fruit.__dict__)
return Response(response)
def post(self, request):
request_data = request.data
item = {'Name': {'S': request_data['Name']}}
if 'Price' in request_data:
item['Price'] = {'N': request_data['Price']}
dynamodb_client.put_item(
TableName = 'Fruits',
Item = item
)
return Response(status=status.HTTP_201_CREATED)
class DynamoDetailRequest(APIView):
#単体GET
def get(self, request, pk):
item = dynamodb_client.get_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)['Item']
fruit = Fruit(item['Name']['S'])
fruit.price = item.get('Price',{}).get('N', '')
return Response(fruit.__dict__)
def put(self, request, pk):
request_data = request.data
item = dynamodb_client.get_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)['Item']
price = item.get('Price',{}).get('N', '0')
if 'Price' in request_data:
price = request_data['Price']
dynamodb_client.put_item(
TableName = 'Fruits',
Item = {
'Name': {'S': item['Name']['S']},
'Price': {'N': price}
}
)
return Response(status=status.HTTP_200_OK)
def delete(self, request, pk):
dynamodb_client.delete_item(
TableName = 'Fruits',
Key = {
'Name': {'S': pk},
}
)
return Response(status=status.HTTP_204_NO_CONTENT)
rest_framework
のAPIView
を継承したclass
でリクエストを処理する。
DynamoRequest
がpathパラメータなしのリクエストを処理し、DynamoDetailRequest
でpathパラメータ(pk)ありのリクエストの処理を行う。
APIView
を継承することにより、HTTPメソッドごとにfunctionを用意することでそれぞれのメソッドに対応する処理を追加することができる。
urls.pyの編集
api/urls.py
from django.urls import path
from api import views
urlpatterns = [
path('api/', views.DynamoRequest.as_view()),
path('api/<pk>/', views.DynamoDetailRequest.as_view())
]
from django.urls import path
from api import views
urlpatterns = [
path('api/', views.DynamoRequest.as_view()),
path('api/<pk>/', views.DynamoDetailRequest.as_view())
]
dynamo_opration
フォルダのurls.py
も編集する
from django.urls import path, include
urlpatterns = [
path('', include('api.urls')),
]
curlコマンドで動作確認
serverの起動
$ python manage.py runserver
GET(全体検索)
$ curl http://127.0.0.1:8000/api/
# レスポンス
[{"name":"orange","price":"200"},{"name":"banana","price":"100"},{"name":"apple","price":"100"}]
POST
$ curl -X POST \
-H 'Content-Type:application/json' \
-d '{"Name": "peach", "Price": "400"}' \
http://127.0.0.1:8000/api/
$ python manage.py runserver
$ curl http://127.0.0.1:8000/api/
# レスポンス
[{"name":"orange","price":"200"},{"name":"banana","price":"100"},{"name":"apple","price":"100"}]
$ curl -X POST \
-H 'Content-Type:application/json' \
-d '{"Name": "peach", "Price": "400"}' \
http://127.0.0.1:8000/api/
peachの項目が追加されている。
GET(単体)
appleの項目を取得
$ curl http://127.0.0.1:8000/api/apple/
# レスポンス
{"name":"apple","price":"100"}
PUT
appleのpriceを100 -> 200へ変更する
$ curl -X PUT \
-H 'Content-Type:application/json' \
-d '{"Price": "200"}' \
http://127.0.0.1:8000/api/apple/
DELETE
peachの項目を削除する。
$ curl -X DELETE http://127.0.0.1:8000/api/peach/
おわりに
django REST Framework + boto3でDynamoDBの操作を行うREST Apiを作成した。
今回は、dynamodb_model.pyを用意してmodelを管理するようにしたが、必要なかったかもしれない(この辺の設計は今後改善していきたい)。
Author And Source
この問題について(Django REST Frameworkでdynamodbを操作するREST APIを作成する), 我々は、より多くの情報をここで見つけました https://qiita.com/yufuku/items/f386f01d7ff9c8d60298著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .