クエリセットの評価タイミングで、正しくない動作をしていたコードを修正したので、メモです。
ダメだったコード
ダメ
def update():
update_user_ids = Users.object.filter(status=True).values_list('id').all()
update_count = Users.object.filter(status=True).update(status=Fasle)
return update_count, update_user_ids
この関数では、updateしたuserのidとその件数を返すものです。
しかし、実際に更新したupdate_count
とupdate_user_ids
の件数が異なっていました。(update_user_ids
は空の配列)
クエリセットの評価タイミング
update_user_ids = Users.object.filter(status=True).values_list('id').all()
この時点では、update_user_idsにクエリセットが構築されただけで、実際にDBへのアクセスは行われていません。
クエリが実行されるのは、実際の値が必要になったタイミングです。(遅延評価というみたい)
update前の結果を代入したつもりですが、実際には評価されておらず、update後に評価されると対象はすでに存在せず、空の配列が返っていました。
正しい
def update():
update_user_ids = list(Users.object.filter(status=True).values_list('id').all())
update_count = Users.object.filter(status=True).update(status=Fasle)
return update_count, update_user_ids
list()
にすることで評価されて、update前の値を取得します。
(この記事書いていて思ったのですが、return update_user_ids, update_count
の返り値の順番を入れ替えてもできるのでは・・・)
参考