pynamodbのクエリで取得したアイテムは辞書型で見れます。本当です😠
はじめに
pynamodbを使ってDynamoDBとの処理を実装してみてます。
コードの方は、公式や、先人たちのブログを参考にしたところ、特に問題なく動いたのですが、クエリで取得したアイテムの取り方ってもっとスマートにいかないものかなと思い調べたところ、良い感じに実装できましたので備忘します。
何がスマートじゃないのか
公式にもサンプルコードあり、以下のようなコードでpynamodbでDynamoDBにクエリしてアイテムを取得できますが、コード中コメントに記載の通り、属性が増える場合にここのコードが増えていくのがスマートでないのです。
class ToDoModel(Model):
class Meta:
table_name = ENV_DB_TABLE_NAME
region = ENV_DYNAMODB_REGION
userid = UnicodeAttribute(hash_key=True)
todoid = UnicodeAttribute(range_key=True)
title = UnicodeAttribute(null=True)
text = UnicodeAttribute(null=True) # ←属性が増える度、書き足さなきゃいけないけど、これはしょうがない。
for item in ToDoModel.query(userid, limit=int(limit)):
res.append({'todoid': item.todoid,
'title': item.title,
'text': item.text # ←属性が増える度、書き足さなきゃいけない!これはどうにかしたい。
})
どうやって見れるとスマートなのか
なんとこれで、辞書型で取れちゃいます。
for item in ToDoModel.query(userid, limit=int(limit)):
itemattr = item.attribute_values
print("itemattr type : {}".format(type(itemattr)))
print("itemattr : {}".format(itemattr))
pynamodb.modelsでは、attribute_values
という変数に辞書型でプロパティと値の組み合わせを入れてくれています。
ちなみに、以下でも同じ結果となります。
for item in ToDoModel.query(userid, limit=int(limit)):
itemattr = vars(item)["attribute_values"]
print("itemattr type : {}".format(type(itemattr)))
print("itemattr : {}".format(itemattr))
vars()
はオブジェクトのプロパティと値の組み合わせを辞書型で取得できます。
vars()
は、オブジェクトの__dict__
を辞書として返します。
全てのオブジェクトにこの__dict__
あるわけではないのですが、今回、自作したクラスToDoModel
のインスタンスは__dict__
属性があるので取得できます。
また、指定されたオブジェクトに__dict__
属性がない場合 、TypeError例外が送出されますが今回はあるので不要ですね。
また、__dict__
を直接見ることもできますが推奨されていないのでやめましょう。
結局、vars()
で__dict__
を参照しているので何ともですが。
上記のprint出力結果例です。
itemattr type : <class 'dict'>
itemattr : {'text': 'テキストテキスト', 'title': 'タイトルタイトル', 'todoid': '2222', 'userid': 'b7d4eac8-e071-70cf-6cbb-xxxxxxx'}
ちなみに不要なキー:値は、pop()
で削除できます。辞書型なので。
itemattr.pop('userid')
削除後
itemattr type : <class 'dict'>
itemattr : {'text': 'テキストテキスト', 'title': 'タイトルタイトル', 'todoid': '2222'}
最後に
__dict__
などの組み込み属性(アトリビュート)や、メソッドについて、以下の説明がとても分かりやすくまとまっていました。
Pythonのメソッドについて正しく理解する
Python中級者になるには、オブジェクト指向の理解が必須ですね。精進して参ります。
Discussion