django - Django 过滤视图集,需要对所有过滤行进行注释。按“全部”分组?
问题描述
这里有数百个关于各种 django 注释/聚合结构和过滤器的问题,但我找不到这个简单的用例被问(或回答)。
我有一个“Payments”模型和关联的 ListAPIView ViewSet 端点以及很好的设置 DjangoFilters,因此客户端可以过滤 created__lte、created__gte、company= 等。
现在我想添加一个从上面派生的端点,但只返回一些字段的总和和过滤对象的总数。
如果我只是“从头开始”编写视图(我可以将 DRF 视图破解为执行 get_queryset().aggregate() 然后输入序列化程序并返回),我确切地知道如何做到这一点,但我想这样做如果可能的话,以“Django 方式”。
例如,结合定义“total_amount”和“nbr”的序列化程序,这(几乎)有效:
queryset = models.Payment.objects.values('company').annotate(total_amount=Sum('amount'),
nbr=Count('id'))
values() 按“company”(付款的子字段)调用分组,结合 annotate() 对所有公司付款执行求和,并使用 total_amount/nbr 进行注释。添加过滤查询参数可以神奇地调整注释中的内容。
问题是,如果我不想按“公司”分组(甚至过滤),我只想“按所有人分组”怎么办?有没有办法做到这一点?
我意识到这已经有点神奇了,但据我所知,Django 式的注释分组方式是这样的。
我也意识到我可能真的更好,只是通过劫持 .retrieve() 来评估查询集,最后加上 .aggregate() 并即时创建响应......虽然仍然很好奇:)
解决方案
我最终得到了“hack”,在视图中使用 .aggregate 调用覆盖 list(),并通过序列化程序将其打包以用于响应。这是我能想到的最规范的方式(我的意思是,尽可能多地重用 Django/DRF 的移动部分,例如查询集的自动过滤、序列化等)。
奖励:注意需要的 Coalesce() 包装,因为如果集合为空,Sum() 不会返回 0。
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
stats = queryset.aggregate(total_amount=Coalesce(Sum('amount'), 0),
total_vat=Coalesce(Sum('vat'), 0),
nbr_payments=Count('id'))
# .aggregate() returns a dict of the results, not a QuerySet. Wrap it
# into a response through the serializer.
sclass = self.get_serializer_class()
return Response(sclass(stats).data)
推荐阅读
- android - Xamarin.Auth 的 AccountStore.Save 在仿真中工作,但不是在“真实”设备上
- javascript - Jquery 替代 DOMSubtreeModified
- javascript - 如何正确读取邮件中附件的 url?
- ios - 如何将 UIBarButtonItem 放在 Swift4 上 NavigationController 的 ViewController 上?
- r - 使用 R 中的年度数据的美国地图 ggplots 的 Gif
- string - 如何在 Python 中多次替换和更新字符串?
- javascript - 如何将事件侦听器添加到循环中的按钮
- shell - 在unix中将最后一列分成两半
- php - 在 apache 中删除 .html 和 .php 的扩展名
- selenium - 点击收音机