※model, urlsの定義は割愛します。
DBオブジェクト操作時、values(‘カラム名’).annotate(…)の順で書くと、カラム名でGROUP BYされた動きになります。
またvaluesするときでもannotateするときでも、’ラベル=カラム名’とすると、別名(ラベル名)で受け取れます。
1 2 3 4 5 |
#例)社員のタスク時間を集計して降順にソート model = Task groupby_employee = Task.objects.values('employee').annotate( total=Sum('task_time'), ).order_by('total').reverse() |
select_related を加えるとで外部キー参照している親テーブルをJOINできます。
1 2 3 4 5 |
#例)社員のタスク時間を集計して降順にソート(社員名が定義されている親テーブルをJOIN) model = Task groupby_employee = Task.objects.select_related().values('employee').annotate( total=Sum('task_time'), ).order_by('total').reverse() |
親テーブルをJOINした時、values に ‘キー_親テーブルのカラム名’を指定すると、親テーブルの値を取得できます。
1 2 3 4 5 6 7 8 9 |
#例)社員のタスク時間を集計して降順にソート(社員名が定義されている親テーブルをJOIN) # さらに社員名も取得 model = Task groupby_employee = Task.objects.select_related().values( 'employee', 'employee__full_name' ).annotate( total=Sum('task_time'), ).order_by('total').reverse() |
具体的なview.py、templateの内容は以下のようになります。
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import TemplateView from django.db.models import Sum class TaskStatsView(LoginRequiredMixin, TemplateView): model = Task template_name = 'template.html' # getメソッドをオーバーライドするパターン def get(self, request, **kwargs): # 社員のタスク時間を集計して降順にソート(社員名が定義されている親テーブルをJOIN。さらに社員名も取得) groupby_employee = Task.objects.select_related().values( 'employee', 'employee__full_name' ).annotate( total=Sum('task_time'), ).order_by('total').reverse() context = { 'groupby_employee' : groupby_employee, } return self.render_to_response(context) |
template.html
別名を付けたものは辞書型で取り出せます。別名付けなかった場合は、Sumしたものであれば ‘カラム名__sum’ の形で取り出せます。
1 2 3 4 5 6 7 8 9 10 11 12 |
<table> {% for e in groupby_employee %} <tr> <!-- 親テーブルから参照した社員名 --> <td>社員名:{{ e.employee__full_name|default:"(社員名未設定)" }}</td> <!-- totalという名前を付けた値 = Sum('task_time') --> <td>総タスク時間:{{ e.total }}</td> <!-- Sum('task_time')に名前を付けなかった場合 --> <td>総タスク時間:{{ e.task_time__sum }}</td> </tr> {% endfor %} </table> |