【DRF】Django REST FrameworkのSerializerとF()を同時に使う


今回のテーマはdjango.db.modelsにあるFクラスと、DRFのSerializerを使う時に気をつけなければならないことを短く紹介したいと思います。

結論

Serializerをイニシャライズする前に、F()を使って.save()したインスタンスに対して、
instance.refresh_from_db()
を呼びましょう。

説明

基本的に、Fを使った後にインスタンスの情報にアクセスしたいなと思ったときにはこれを思い出すといいと思います。もちろんSerializerに限る話ではありません。

例えば、いいね機能を実装しているとします。
いいねをすると言う機能は、ユーザーが同時に大量にアクセスすることがあり得るので、Fを使うことでちゃんと+1、-1されるように実装します。

しかし、Serializerでシリアライズするときに内部では、定義されたフィールドに応じて型がキャストされるので、F('count') + 1のような表現は許容されません。

F('count') + 1のような表現はCombinedExpressionと呼ばれていて、int型に変換することはできませんよというエラーが出てしまいます。

それを回避するために、いったんDBとのやりとりをリフレッシュすることで、モデルのインスタンスから正しい形の(Fが走り終えた後の)データを取得することができ、正しくシリアライズすることができるようになります。

さらに詳しい説明は、Django refresh_from_db

コロナに負けず頑張りましょう!