有没有一种方法可以在Django Rest Framework中聚合一个字段,该字段将具有一个字段的总和

时间:2019-04-29 12:40:40

标签: django django-rest-framework django-rest-viewsets

目前,我已经弄清楚如何在序列化器中汇总单个列。py,但是我的薪金字段的总和将进入我的序列化器中的total_salary 字段和 total_salary 不在我的模型中。现在我的问题是我该如何在下面的API中执行以下操作:

"total_salary": 1422.05,
{
        "id": "8c1810d9-b799-46a9-8506-3c18ef0067f8",
        "date": "2019-04-27",
        "virtual_assistant": "Joevie",
        "time_in": "2019-04-27T22:20:13+08:00",
        "time_out": "2019-04-28T05:20:13+08:00",
        "hours": "7.00",
        "client_name": "landmaster",
        "rate": "90.00",
        "salary": "630.00",
        "status": "APPROVED-BY-THE-MANAGER",
        "notes": ""
    },

现有的就是这样。

 {
        "id": "8c1810d9-b799-46a9-8506-3c18ef0067f8",
        "total_salary": 1422.05,
        "date": "2019-04-27",
        "virtual_assistant": "Joevie",
        "time_in": "2019-04-27T22:20:13+08:00",
        "time_out": "2019-04-28T05:20:13+08:00",
        "hours": "7.00",
        "client_name": "landmaster",
        "rate": "90.00",
        "salary": "630.00",
        "status": "APPROVED-BY-THE-MANAGER",
        "notes": ""
 },

目前,我所采取的解决方法是,从现在起,以及每次用户搜索特定月份时,我都在ListView中获得工资的总和。计算将根据用户搜索的月份而变化。下面的代码。

def get(self, request, *args, **kwargs):
        search = request.GET.get('search')
        user = request.user.staffs.full_name
        current_month = datetime.date.today().month
        current_year = datetime.date.today().year
        payroll_list = VaPayroll.objects.all()
        payroll_data = payroll_list.filter(Q(virtual_assistant=user),
                                           Q(date__month=current_month),
                                           Q(status='APPROVED-BY-THE-MANAGER'))
        total_salary = VaPayroll.objects.filter(Q(virtual_assistant=user), 
                                                Q(date__month=current_month),
                                                Q(status='APPROVED-BY-THE-MANAGER'),
                                                Q(date__year=current_year)).aggregate(Sum('salary'))
        if search:
            payroll_data = payroll_list.filter(Q(virtual_assistant=user),
                                               Q(status='APPROVED-BY-THE-MANAGER'),
                                               Q(date__icontains=search))
            total_salary = VaPayroll.objects.filter(Q(virtual_assistant=user),
                                                    Q(status='APPROVED-BY-THE-MANAGER'),
                                                    Q(date__month=search),
                                                    Q(date__year=current_year)).aggregate(Sum('salary'))
        context = {
            'total_salary': total_salary,
            'payroll_data': payroll_data
        }
        return render(request, self.template_name, context)

这是来自我的serializers.py

class VaPayrollSerializer(serializers.ModelSerializer):
    total_salary = serializers.SerializerMethodField()

    class Meta:
        model = VaPayroll
        fields = '__all__'

    def get_total_salary(self, obj):
        user = self.context['request'].user.staffs.full_name
        totalsalary = VaPayroll.objects.filter(Q(status='APPROVED-BY-THE-MANAGER'),
                                               Q(virtual_assistant=user),
                                               Q(date__month=datetime.date.today().month),
                                               Q(date__year=datetime.date.today().year)).aggregate(total_salary=Sum('salary'))
        return totalsalary['total_salary']

这是从我的模型视图集中获得的 get_queryset

def get_queryset(self):
        current_month = datetime.date.today().month
        current_year = datetime.date.today().year
        queryset = VaPayroll.objects.filter(Q(virtual_assistant=self.request.user.staffs.full_name), 
                                            Q(date__month=current_month), 
                                            Q(date__year=current_year))
        return queryset

在我计划的用例中,我希望我的API中有一个单独的列,该列将包含所有薪水的总和,以便我可以在前端中单独调用该字段,而无需刷新页面以重新计算总工资。还是这是正确的方法?还是我应该坚持使用View来重新计算总工资。

1 个答案:

答案 0 :(得分:1)

您无法以所需的方式获取json,因为它不是有效的json格式。我的建议是尝试这样的事情:

"salary": {
           "total": 1422.05,
           "detail": {
                      "id": "8c1810d9-b799-46a9-8506-3c18ef0067f8",
                      "date": "2019-04-27",
                      "virtual_assistant": "Joevie",
                      "time_in": "2019-04-27T22:20:13+08:00",
                      "time_out": "2019-04-28T05:20:13+08:00",
                      "hours": "7.00",
                      "client_name": "landmaster",
                      "rate": "90.00",
                      "salary": "630.00",
                      "status": "APPROVED-BY-THE-MANAGER",
                      "notes": ""
             }
      }

为此,您必须使用to_representation()方法来指示序列化程序:

class VaPayrollSerializer(serializers.ModelSerializer):
    class Meta:
        model = VaPayroll
        fields = '__all__'

    def to_representation(self, instance):
        original_representation = super().to_representation(instance)

        representation = {
            'total': self.get_total_salary(instance),
            'detail': original_representation,
        }

        return representation

    def get_total_salary(self, obj):
        user = self.context['request'].user.staffs.full_name
        totalsalary = VaPayroll.objects.filter(Q(status='APPROVED-BY-THE-MANAGER'),
            Q(virtual_assistant=user),
            Q(date__month=datetime.date.today().month),
        Q(date__year=datetime.date.today().year)).aggregate(total_salary=Sum('salary'))

        return totalsalary['total_salary']