クエリセットで、DurationFieldの値を、掛けたり割ったりしたものを取得したい時があります。たとえばチームの作業で1人当たり何分かっかったのか、とか、1mあたり何分くらいかかっているのか、とか。
しかし、以下のようなクエリセットを構築し、レンダリングしようとすると怒られます。
1 2 3 4 5 6 7 |
from django.db.models import(Sum, F,)<br> queryset = Example.objects.annotate( total_time=Sum('time'), # かかった時間 total_people=Sum('people'), # 人数 # 1人あたりの所要時間 rate=F('total_time')/F('total_people'), ) |
“sqlite Invalid connector for timedelta: /” と言われてまして、どうやらSQLiteではtimedelta形式の値(Durationフィールド)をそのまま除算できないようで、”/”が不正なコネクタとして認識されてしまいます。
DjangoのDuration型は、SQLite3ではbigint型となります。(Djangoのフィールド型とDBの型の組合せはこちらを参照)
MySQLなどでは大丈夫とのことですが、SQLiteではバグか何かしりませんが、同じintなのに、bigint型を直接計算できない模様。
いろいろ試した結果、Djangoで型を合わせればイケルというこうとがわかったので、今回はDurationを、割る方のintegerに合わせます。
クエリセット作成時に、Castしてoutput_fieldを指定してやればOKです。Durationをintegerに変換すると、100万分の1秒が整数1位で返るので、秒単位にするには1,000,000で割ってやります。
1 2 3 4 5 6 7 8 9 10 |
from django.db.models import(Sum, F, IntegerField,) from django.db.models.functions import Cast queryset = Example.objects.annotate( total_time=Sum('time'), # かかった時間 total_people=Sum('people'), # 人数 # 1人あたりの所要時間 #rate=F('total_time')/F('total_people'), rate=Cast(Sum('time'), IntegerField())/ 1000000 / Sum('people') , ) |
これで、テンプレート側では、以下で取得できます。
1 2 3 4 5 6 7 |
{% for e in example_list %} <li>時間:{{ e.total_time }}</li> <li>人数:{{ e.total_people }} 人</li> <li>効率:{{ e.rate }} 秒/人</li> {% empty %} <li>データが見つかりません</li>。 {% endfor %} |