😠

pynamodbのクエリで取得したアイテムは辞書型で見れます。本当です😠

2023/06/25に公開

はじめに

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