#author("2018-09-09T15:06:54+00:00","","") [[AWSメモ]] > * PythonでAWS DynamoDBのCRUDを書いてみる [#w8a52561] #setlinebreak(on); #contents -- 関連 --- [[AWS Java SDKでDynamoDBのCRUDを書いてみる]] ** 概要 [#xd911e47] #html(<div class="pl20">) Python で DynamoDB へのCRUDを書いてみる。 尚、今回は GET、POST、PUT、DELETE ハンドラーをそれぞれ別々に作成する。 https://github.com/awslabs/serverless-application-model/tree/master/examples/2016-10-31/api_backend #html(</div>) ** 参考 [#h78b1d6b] #html(<div class="pl20">) http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStarted.Python.03.html http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html http://boto3.readthedocs.io/en/latest/guide/dynamodb.html #html(</div>) ** テーブル作成 [#z86e5b6a] *** テーブル定義の作成 [#ka94cfa2] ddl/books.json #mycode2(){{ { "TableName": "Books", "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" }, { "AttributeName": "isbn", "AttributeType": "S" }, { "AttributeName": "title", "AttributeType": "S" } ], "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "ProvisionedThroughput": { "WriteCapacityUnits": 1, "ReadCapacityUnits": 1 }, "GlobalSecondaryIndexes": [ { "IndexName": "isbn-index", "KeySchema": [ { "AttributeName":"isbn", "KeyType":"HASH" } ], "Projection": {"ProjectionType": "KEYS_ONLY" }, "ProvisionedThroughput": {"ReadCapacityUnits": 1,"WriteCapacityUnits": 1 } }, { "IndexName": "title-index", "KeySchema": [ { "AttributeName":"title", "KeyType":"HASH" } ], "Projection": {"ProjectionType": "KEYS_ONLY" }, "ProvisionedThroughput": {"ReadCapacityUnits": 1,"WriteCapacityUnits": 1 } } ] } }} *** テーブル作成 [#efb826d2] #myterm2(){{ aws dynamodb create-table --endpoint-url http://localhost:8000 --cli-input-json file://ddl/books.json }} ※ローカルのDynamoDBでない場合は --endpoint-url は不要。 ** Lambda関数の作成 [#z5c813af] #html(<div style="padding-left:20px;">) book.js #mycode2(){{ import os import boto3 import json import decimal dynamodb = None if os.environ and os.environ["DYNAMO_REGION"] and os.environ["DYNAMO_END_POINT"]: dynamodb = boto3.resource('dynamodb', region_name=os.environ["DYNAMO_REGION"], endpoint_url=os.environ["DYNAMO_END_POINT"]) else: dynamodb = boto3.resource('dynamodb', dynamo_opt) # テーブル名 TABLE_NAME = "Books" # 一覧 def list(event, context): res = dynamodb.Table(TABLE_NAME).scan() return { 'body' : str(res) } # 一意検索 def get(event, context): res = dynamodb.Table(TABLE_NAME).get_item( Key={ "id" : event["pathParameters"]["id"] } ) return { 'body' : str(res) } # 登録 def create(event, context): req = json.loads(event["body"]) if type(event["body"]) == str else event["body"] res = dynamodb.Table(TABLE_NAME).put_item( Item={ "id": req["id"], "isbn": req["isbn"], "title": req["title"], "price": decimal.Decimal(req["price"]) } ) return { 'body' : str(res) } # 更新 def update(event, context): req = json.loads(event["body"]) if type(event["body"]) == str else event["body"] res = dynamodb.Table(TABLE_NAME).update_item( Key={ 'id': event["pathParameters"]["id"] }, UpdateExpression="set isbn=:i, title=:t, price=:p", ExpressionAttributeValues={ ':i': req["isbn"], ':t': req["title"], ':p': decimal.Decimal(req["price"]) }, ReturnValues="UPDATED_NEW" ) return { 'body' : str(res) } # 削除 def delete(event, context): res = dynamodb.Table(TABLE_NAME).delete_item( Key={ 'id': event["pathParameters"]["id"] } ) return { 'body' : str(res) } }} #html(</div>) ** template.yml の作成 [#fa6a8b2f] #html(<div style="padding-left:20px;">) template-local.yml #mycode2(){{ AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Test serverless application. Resources: BookListFunction: Type: AWS::Serverless::Function Properties: Handler: book.list Policies: AmazonDynamoDBFullAccess Runtime: python3.6 MemorySize: 128 Timeout: 5 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 DYNAMO_REGION: localhost Events: List: Type: Api Properties: Path: /book Method: get BookGetFunction: Type: AWS::Serverless::Function Properties: Handler: book.get Policies: AmazonDynamoDBFullAccess Runtime: python3.6 MemorySize: 128 Timeout: 5 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 DYNAMO_REGION: localhost Events: Get: Type: Api Properties: Path: /book/{id} Method: get BookCreateFunction: Type: AWS::Serverless::Function Properties: Handler: book.create Policies: AmazonDynamoDBFullAccess Runtime: python3.6 MemorySize: 128 Timeout: 5 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 DYNAMO_REGION: localhost Events: Create: Type: Api Properties: Path: /book Method: post BookUpdateFunction: Type: AWS::Serverless::Function Properties: Handler: book.update Policies: AmazonDynamoDBFullAccess Runtime: python3.6 MemorySize: 128 Timeout: 5 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 DYNAMO_REGION: localhost Events: Update: Type: Api Properties: Path: /book/{id} Method: put BookDeleteFunction: Type: AWS::Serverless::Function Properties: Handler: book.delete Policies: AmazonDynamoDBFullAccess Runtime: python3.6 MemorySize: 128 Timeout: 5 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 DYNAMO_REGION: localhost Events: Delete: Type: Api Properties: Path: /book/{id} Method: delete }} #html(</div>) ** sam local 上で api を起動 [#h62ee7e2] #html(<div class="pl20">) [[AWS Lambda のローカル開発手順]] も参照 #myterm2(){{ sam local start-api --template template-local.yml }} #html(</div>) ** 動作確認 [#w02ea84b] #html(<div class="pl20">) *** 一覧 [#kbd7d608] #myterm2(){{ curl http://localhost:3000/book }} *** 登録 [#v74ca8c9] #myterm2(){{ curl -XPOST -H 'Content-type: application/json' --data '{ "id" : "A01", "isbn" : "ABC001", "title" : "テスト001", "price": 1008 }' http://localhost:3000/book curl -XPOST -H 'Content-type: application/json' --data '{ "id" : "A02", "isbn" : "ABC002", "title" : "テスト002", "price": 2016 }' http://localhost:3000/book }} *** 更新 [#l6c32025] #myterm2(){{ curl -XPUT -H 'Content-type: application/json' --data '{ "isbn" : "XXXXX1", "title" : "テストXX1", "price": 108 }' http://localhost:3000/book/A01 }} *** 削除 [#badccae6] #myterm2(){{ curl -XDELETE http://localhost:3000/book/A01 }} #html(</div>)