DjangoのQuerySetでannotateで生成したtimedeltaをfilterしたいとき

今回はDjangoのQuerySetを使っているときにannotateで日付の比較などを行って生成したカラムに対してfilter条件で抽出したいときどのようにすれば良いのかについてご紹介いたします。



DjangoのQuerySetでannotateで生成したtimedeltaをfilterしたいとき

例としてEventというモデルがあって、DateTimeFieldのdatetime_fromとDateTimeFieldのdatetime_toがEventモデルにあったとしましょう。
annotate関数を使って、datetime_toとdatetime_fromの差であるevent_timeを取得するとします。
上記の例では、一旦F関数を使って

というソースコードが書けると思います。

さて、上記のときにevent_timeが120秒以上のものを抽出したいとしましょう。
単純にfilter条件だけではエラーが出てしまいます。

ここで、Eventモデルの新しく設定したevent_timeの値を見てみると、
datetime.timedelta(seconds=17000)
などの値が出力されていると思います。(私の動作実行時の環境はPostgresSQL環境です)

つまり、このままでは型も合ってそうにないのでうまくいかなそうなことが分かると思います。

結論を言うと、ExpressionWrapperとtimedeltaを使うようにしましょう。

先にコード例を書くと下記のようになります。

ExpressionWrapperを使ってannotateで新しく追加したカラムをDurationFieldとして出力するようにしましょう。
その後DurationFieldとして出力した結果に対して、timedeltaの型でfilter条件で抽出すればOKです。

注意点としては、DurationFieldはPostgreSQLではうまく動作しますが、他のDB環境ではうまく動作しない場合があるようです。
DBの環境にも注意するようにしましょう。

終わりに

今回はDjangoのQuerySetを使っているときにannotateで日付の比較などを行って生成したカラムに対してfilter条件で抽出したいときどのようにすれば良いのかについてご紹介いたしました。

最後までお読みいただきありがとうございます。
よろしければブログやTwitterでのシェアをお願いしております。
コメントもお待ちしております。
誤植や勘違いなどございましたらコメント欄にて教えていただけると幸いです。

直接契約ができるフリーランスエージェント「エンハンス」を立ち上げました。
詳しくは下記LPをご参照ください。
https://enhance.decryption.co.jp/

Youtubeチャンネル開設いたしました。
チャンネル登録者10,000人を目指しているので、良いと思った方はチャンネル登録をお願いしたいです。
https://www.youtube.com/channel/UC219XhmSRxmXltTy6COxSMw






Django

Posted by ちこ