如何在Django中根据用户传入的动态日期范围返回对应金额总和
解决方案
核心思路
通过字典动态组装查询过滤条件,再用**关键字参数解包的方式传给filter方法,即可适配任意用户传入的动态参数,不需要硬编码固定的过滤条件。
具体实现
你当前的视图绑定的是CustomerVisit模型,和你要查询Payment表求和的需求不符,调整后的视图代码如下:
from django.db.models import Sum from rest_framework.response import Response class UserWiseCollectionView(ListAPIView): permission_classes = [IsAuthenticated,] # 调整为Payment模型 model = Payment serializer_class = UserWiseCollectionSerializer filter_backends = [DjangoFilterBackend] filterset_fields = ['created_by', 'mode', 'is_settlement'] # 可扩展更多支持过滤的字段 def list(self, request, *args, **kwargs): # 初始化过滤参数字典 filter_kwargs = {} # 逐个校验参数,存在则加入过滤字典 created_by = request.query_params.get('created_by') if created_by: filter_kwargs['created_by_id'] = int(created_by) # 外键字段可以用_id直接传入主键值 start_date = request.query_params.get('start_date') end_date = request.query_params.get('end_date') if start_date and end_date: filter_kwargs['created_at__range'] = [start_date, end_date] mode = request.query_params.get('mode') if mode: filter_kwargs['mode'] = mode # 其他需要支持的参数都可以按这个格式加 # 执行过滤+聚合查询 total = Payment.objects.filter(**filter_kwargs).aggregate(total=Sum('amount'))['total'] # 兜底无匹配数据时为0 total = total if total is not None else 0 # 如果你同时需要返回列表+总和,可以保留原有查询逻辑,把总和加到响应里 queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response({ 'list': serializer.data, 'total_amount': total }) serializer = self.get_serializer(queryset, many=True) return Response({ 'list': serializer.data, 'total_amount': total })
注意事项
- 可以根据业务需求增加参数校验逻辑,比如校验日期格式是否合法、传入的created_by是否为存在的员工ID,避免触发查询异常
- 后续需要新增过滤条件时,只需要按照示例格式往
filter_kwargs字典中新增对应键值对即可,扩展成本极低 - 如果不需要返回支付明细列表,只需要返回总和,可以直接删除列表查询相关的代码,只保留聚合查询的逻辑,简化接口实现
内容的提问来源于stack exchange,提问作者spraj
相关产品推荐
相关产品推荐

