Django REST Framework에서 dynamodb와 상호 작용하는 REST API 만들기

소개



django REST Framework와 boto3에서 AWS DynamoDB에 대한 작업을 수행하는 api를 만듭니다.
GET, POST, PUT, DELETE의 조작을 할 수 있도록 한다.

Dynamodb 테이블 작성 (사전 준비)



아래와 같은 테이블을 사전에 준비해, 몇개의 데이터를 넣어 둔다
테이블 이름: Fruits
hash key: Name



장고 프로젝트 만들기



장고 프로젝트 (dynamo_operation)와 app (api) 만들기
$ django-admin startproject dynamo_operation
$ cd dynamo_operation/
$ django-admin startapp api 

setting.py 수정


setting.pyrest_framework 와 방금 만든 app 의 config 를 추가한다.

dynamo_operation/setting.py
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 요청에 대한 모델 만들기



django에서는 DB의 작성, 조작에 model를 준비한다.
DynamoDB에 대한 요청은 boto3을 사용하므로 특히 model는 필요하지 않지만 이번에는 model(dynamo_model.py)를 준비했습니다.

api/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)
rest_frameworkAPIView를 상속받은 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())
]
dynamo_opration 폴더의 urls.py
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/

POST 요청 후 테이블


peach 항목이 추가되었습니다.

GET(단체)



애플 아이템 얻기
$ curl http://127.0.0.1:8000/api/apple/

# レスポンス
{"name":"apple","price":"100"}

PUT



애플의 가격을 100 -> 200으로 변경
$ curl -X PUT \
  -H 'Content-Type:application/json' \
  -d '{"Price": "200"}' \
  http://127.0.0.1:8000/api/apple/

PUT 요청 후 테이블


DELETE



peach 항목을 삭제합니다.
$ curl -X DELETE http://127.0.0.1:8000/api/peach/

DELETE 요청 후 테이블


결론



django REST Framework + boto3에서 DynamoDB 작업을 수행하는 REST Api를 만들었습니다.
이번에는 dynamodb_model.py를 준비하여 모델을 관리하도록 했지만 필요 없었을지도 모른다 (이 근처의 설계는 앞으로 개선하고 싶다).

좋은 웹페이지 즐겨찾기