DRF:如何对Serializermethodfield创建的自定义字段进行排序

发布于 2025-01-30 18:22:49 字数 6664 浏览 1 评论 0原文

我已经创建了序列化嵌套是用作文档

model.py

class Category(models.Model):
    name = models.CharField("Name", "name", max_length=255)
    iconname = models.CharField("Icon Name", "iconname", max_length=255)
    budgetamount = models.DecimalField(
        max_digits=19, decimal_places=2, default=0)
    iconcolor = models.CharField(
        "Icon Color", "iconcolor", default='4294951175', max_length=255)

    def __str__(self):
        return self.name


class DailyExpense(models.Model):
    payee_item_desc = models.CharField(
        "Payee Item Description", "payee_item_desc", max_length=255)
    category = models.ForeignKey(
        Category, related_name='dailyexpense_category', on_delete=models.CASCADE, blank=True, null=True)
    amount = models.DecimalField(max_digits=19, decimal_places=2)
    remarks = models.CharField(
        "Remarks", "remarks", max_length=255, blank=True, null=True)
    tran_date = models.DateTimeField()
    isnotclear = models.BooleanField(default=False)

    def __str__(self):
        return self.payee_item_desc

serializers.py

class DailyExpenseSerializer(serializers.ModelSerializer):
    class Meta:
        model = DailyExpense
        fields = "__all__"


class CategoryWithDailyExpenseSerializer(serializers.ModelSerializer):
    dailyexpense_category = DailyExpenseSerializer(
        source='filtered_dailyexpense_category', many=True, read_only=True)
    sum_expense = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ('id', 'name', 'iconname', 'sum_expense',
                  'budgetamount', 'iconcolor', 'dailyexpense_category')

    def get_sum_expense(self, obj):
        fromDate = parse_datetime(self.context['request'].query_params.get(
            'fromDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        toDate = parse_datetime(self.context['request'].query_params.get(
            'toDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        return obj.dailyexpense_category.aggregate(sum_expense=Sum('amount', filter=Q(tran_date__range=[fromDate, toDate])))['sum_expense']

views.py

class CategoryWithDailyExpenseViewSet(viewsets.ModelViewSet):

    def get_queryset(self):
        fromDate = parse_datetime(self.request.query_params.get(
            'fromDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        toDate = parse_datetime(self.request.query_params.get(
            'toDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        queryset = Category.objects.prefetch_related(
            Prefetch('dailyexpense_category', queryset=DailyExpense.objects.filter(
                tran_date__range=[fromDate, toDate]).order_by('tran_date'), to_attr='filtered_dailyexpense_category')
        ).annotate(num_daily=Count('dailyexpense_category', filter=Q(dailyexpense_category__tran_date__range=[fromDate, toDate]))).filter(num_daily__gt=0)
        return queryset

    serializer_class = CategoryWithDailyExpenseSerializer
    filter_class = CategoryFilter

而我得到的结果如下

[
    {
        "id": 52,
        "name": "KIRIN HOUSE:Internet",
        "iconname": "signal_cellular_alt",
        "sum_expense": -900.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 25343,
                "payee_item_desc": "ค่าเนต",
                "amount": "-700.00",
                "remarks": "",
                "tran_date": "2022-04-02T00:00:00Z",
                "isnotclear": false,
                "category": 52
            },
            {
                "id": 30166,
                "payee_item_desc": "เนตฟลิก",
                "amount": "-200.00",
                "remarks": "",
                "tran_date": "2022-04-18T00:00:00Z",
                "isnotclear": false,
                "category": 52
            }
        ]
    },
    {
        "id": 50,
        "name": "Gifts",
        "iconname": "card_giftcard",
        "sum_expense": -3000.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 22298,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-2000.00",
                "remarks": "",
                "tran_date": "2022-04-03T00:00:00Z",
                "isnotclear": false,
                "category": 50
            },
            {
                "id": 30161,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-1000.00",
                "remarks": "",
                "tran_date": "2022-04-15T00:00:00Z",
                "isnotclear": false,
                "category": 50
            }
        ]
    }
]

是否想将sum_expense(从serializersmethod中进行自定义字段)为订单最大总费用金额,如下所示,

[
    {
        "id": 50,
        "name": "Gifts",
        "iconname": "card_giftcard",
        "sum_expense": -3000.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 22298,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-2000.00",
                "remarks": "",
                "tran_date": "2022-04-03T00:00:00Z",
                "isnotclear": false,
                "category": 50
            },
            {
                "id": 30161,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-1000.00",
                "remarks": "",
                "tran_date": "2022-04-15T00:00:00Z",
                "isnotclear": false,
                "category": 50
            }
        ]
    },
    {
        "id": 52,
        "name": "KIRIN HOUSE:Internet",
        "iconname": "signal_cellular_alt",
        "sum_expense": -900.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 25343,
                "payee_item_desc": "ค่าเนต",
                "amount": "-700.00",
                "remarks": "",
                "tran_date": "2022-04-02T00:00:00Z",
                "isnotclear": false,
                "category": 52
            },
            {
                "id": 30166,
                "payee_item_desc": "เนตฟลิก",
                "amount": "-200.00",
                "remarks": "",
                "tran_date": "2022-04-18T00:00:00Z",
                "isnotclear": false,
                "category": 52
            }
        ]
    }
]

可以在Django Rest框架中执行此操作,或者我必须以前端语言对其进行排序?

I've created serializing nested be using serializers as document

models.py

class Category(models.Model):
    name = models.CharField("Name", "name", max_length=255)
    iconname = models.CharField("Icon Name", "iconname", max_length=255)
    budgetamount = models.DecimalField(
        max_digits=19, decimal_places=2, default=0)
    iconcolor = models.CharField(
        "Icon Color", "iconcolor", default='4294951175', max_length=255)

    def __str__(self):
        return self.name


class DailyExpense(models.Model):
    payee_item_desc = models.CharField(
        "Payee Item Description", "payee_item_desc", max_length=255)
    category = models.ForeignKey(
        Category, related_name='dailyexpense_category', on_delete=models.CASCADE, blank=True, null=True)
    amount = models.DecimalField(max_digits=19, decimal_places=2)
    remarks = models.CharField(
        "Remarks", "remarks", max_length=255, blank=True, null=True)
    tran_date = models.DateTimeField()
    isnotclear = models.BooleanField(default=False)

    def __str__(self):
        return self.payee_item_desc

serializers.py

class DailyExpenseSerializer(serializers.ModelSerializer):
    class Meta:
        model = DailyExpense
        fields = "__all__"


class CategoryWithDailyExpenseSerializer(serializers.ModelSerializer):
    dailyexpense_category = DailyExpenseSerializer(
        source='filtered_dailyexpense_category', many=True, read_only=True)
    sum_expense = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ('id', 'name', 'iconname', 'sum_expense',
                  'budgetamount', 'iconcolor', 'dailyexpense_category')

    def get_sum_expense(self, obj):
        fromDate = parse_datetime(self.context['request'].query_params.get(
            'fromDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        toDate = parse_datetime(self.context['request'].query_params.get(
            'toDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        return obj.dailyexpense_category.aggregate(sum_expense=Sum('amount', filter=Q(tran_date__range=[fromDate, toDate])))['sum_expense']

views.py

class CategoryWithDailyExpenseViewSet(viewsets.ModelViewSet):

    def get_queryset(self):
        fromDate = parse_datetime(self.request.query_params.get(
            'fromDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        toDate = parse_datetime(self.request.query_params.get(
            'toDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
        queryset = Category.objects.prefetch_related(
            Prefetch('dailyexpense_category', queryset=DailyExpense.objects.filter(
                tran_date__range=[fromDate, toDate]).order_by('tran_date'), to_attr='filtered_dailyexpense_category')
        ).annotate(num_daily=Count('dailyexpense_category', filter=Q(dailyexpense_category__tran_date__range=[fromDate, toDate]))).filter(num_daily__gt=0)
        return queryset

    serializer_class = CategoryWithDailyExpenseSerializer
    filter_class = CategoryFilter

And the result that I got as below

[
    {
        "id": 52,
        "name": "KIRIN HOUSE:Internet",
        "iconname": "signal_cellular_alt",
        "sum_expense": -900.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 25343,
                "payee_item_desc": "ค่าเนต",
                "amount": "-700.00",
                "remarks": "",
                "tran_date": "2022-04-02T00:00:00Z",
                "isnotclear": false,
                "category": 52
            },
            {
                "id": 30166,
                "payee_item_desc": "เนตฟลิก",
                "amount": "-200.00",
                "remarks": "",
                "tran_date": "2022-04-18T00:00:00Z",
                "isnotclear": false,
                "category": 52
            }
        ]
    },
    {
        "id": 50,
        "name": "Gifts",
        "iconname": "card_giftcard",
        "sum_expense": -3000.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 22298,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-2000.00",
                "remarks": "",
                "tran_date": "2022-04-03T00:00:00Z",
                "isnotclear": false,
                "category": 50
            },
            {
                "id": 30161,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-1000.00",
                "remarks": "",
                "tran_date": "2022-04-15T00:00:00Z",
                "isnotclear": false,
                "category": 50
            }
        ]
    }
]

I wanted to sort sum_expense (custom field from SerializersMethod) to be order maximum sum expense amount as below

[
    {
        "id": 50,
        "name": "Gifts",
        "iconname": "card_giftcard",
        "sum_expense": -3000.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 22298,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-2000.00",
                "remarks": "",
                "tran_date": "2022-04-03T00:00:00Z",
                "isnotclear": false,
                "category": 50
            },
            {
                "id": 30161,
                "payee_item_desc": "ให้พ่อ",
                "amount": "-1000.00",
                "remarks": "",
                "tran_date": "2022-04-15T00:00:00Z",
                "isnotclear": false,
                "category": 50
            }
        ]
    },
    {
        "id": 52,
        "name": "KIRIN HOUSE:Internet",
        "iconname": "signal_cellular_alt",
        "sum_expense": -900.0,
        "budgetamount": "0.00",
        "iconcolor": "4294951175",
        "dailyexpense_category": [
            {
                "id": 25343,
                "payee_item_desc": "ค่าเนต",
                "amount": "-700.00",
                "remarks": "",
                "tran_date": "2022-04-02T00:00:00Z",
                "isnotclear": false,
                "category": 52
            },
            {
                "id": 30166,
                "payee_item_desc": "เนตฟลิก",
                "amount": "-200.00",
                "remarks": "",
                "tran_date": "2022-04-18T00:00:00Z",
                "isnotclear": false,
                "category": 52
            }
        ]
    }
]

Is it possible to do this in django rest framework or I have to sort it in front end language?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

软糖 2025-02-06 18:22:49

我认为您可以在Viewset类中设置ordering_fields

class CategoryWithDailyExpenseViewSet(viewsets.ModelViewSet):
    ...
    serializer_class = CategoryWithDailyExpenseSerializer
    filter_class = CategoryFilter
    ordering_fields = ['-sum_expense']

或者,您可以在list函数中添加sort函数。

def list(self, request, *args, *kwargs):
    response = super(CategoryWithDailyExpenseViewSet, self).list(request, args, kwargs)
    response.data = sorted(response.data, key=lambda k: (k['sum_expense'], ))
    return response

I think you can set the ordering_fields in viewset class.

class CategoryWithDailyExpenseViewSet(viewsets.ModelViewSet):
    ...
    serializer_class = CategoryWithDailyExpenseSerializer
    filter_class = CategoryFilter
    ordering_fields = ['-sum_expense']

Or you can add the sort function in list function.

def list(self, request, *args, *kwargs):
    response = super(CategoryWithDailyExpenseViewSet, self).list(request, args, kwargs)
    response.data = sorted(response.data, key=lambda k: (k['sum_expense'], ))
    return response
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文