zoukankan      html  css  js  c++  java
  • Django Rest Framework序列化程序中的聚合(和其他注释)字段

    我试图找出添加注释字段的最佳方法,例如任何聚合(计算)字段到DRF(Model)Serializers.我的用例只是一种端点返回不存储在数据库中而是从数据库计算的字段的情况.

    我们来看下面的例子:

    models.py

    class IceCreamCompany(models.Model):
        name = models.CharField(primary_key = True, max_length = 255)
    
    class IceCreamTruck(models.Model):
        company = models.ForeignKey('IceCreamCompany', related_name='trucks')
        capacity = models.IntegerField()

    serializers.py

    class IceCreamCompanySerializer(serializers.ModelSerializer):
        class Meta:
            model = IceCreamCompany

    所需的JSON输出:

    [
    
        {
            "name": "Pete's Ice Cream",
            "total_trucks": 20,
            "total_capacity": 4000
        },
        ...
    ]

    我有几个解决方案可以工作,但每个都有一些问题.

    选项1:添加getter来建模并使用SerializerMethodFields

    models.py

    class IceCreamCompany(models.Model):
        name = models.CharField(primary_key=True, max_length=255)
    
        def get_total_trucks(self):
            return self.trucks.count()
    
        def get_total_capacity(self):
            return self.trucks.aggregate(Sum('capacity'))['capacity__sum']

    serializers.py

    class IceCreamCompanySerializer(serializers.ModelSerializer):
    
        def get_total_trucks(self, obj):
            return obj.get_total_trucks
    
        def get_total_capacity(self, obj):
            return obj.get_total_capacity
    
        total_trucks = SerializerMethodField()
        total_capacity = SerializerMethodField()
    
        class Meta:
            model = IceCreamCompany
            fields = ('name', 'total_trucks', 'total_capacity')

    上面的代码可能被重构了一点,但是它不会改变这个事实,这个选项将对IceCream公司执行2个额外的SQL查询,这不是非常有效的.

    选项2:在ViewSet.get_queryset中注释

    models.py是最初描述的.

    views.py

    class IceCreamCompanyViewSet(viewsets.ModelViewSet):
        queryset = IceCreamCompany.objects.all()
        serializer_class = IceCreamCompanySerializer
    
        def get_queryset(self):
            return IceCreamCompany.objects.annotate(
                total_trucks = Count('trucks'),
                total_capacity = Sum('trucks__capacity')
            )

    这将在单个SQL查询中获取聚合字段,但是我不知道如何将它们添加到Serializer中,因为DRF不会神奇地知道我在QuerySet中注释了这些字段.如果我将total_trucks和total_capacity添加到序列化程序中,那么它将抛出一个关于模型中不存在的这些字段的错误.

    选项2可以通过使用View而不使用串行器来实现,但是如果模型包含很多字段,并且只有一些需要在JSON中,那么在没有串行器的情况下构建端点将是一个有些丑陋的攻击.

     
    可能的解决方案:

    views.py

    class IceCreamCompanyViewSet(viewsets.ModelViewSet):
        queryset = IceCreamCompany.objects.all()
        serializer_class = IceCreamCompanySerializer
    
        def get_queryset(self):
            return IceCreamCompany.objects.annotate(
                total_trucks=Count('trucks'),
                total_capacity=Sum('trucks__capacity')
            )

    serializers.py

    class IceCreamCompanySerializer(serializers.ModelSerializer):
        total_trucks = serializers.IntegerField()
        total_capacity = serializers.IntegerField()
    
        class Meta:
            model = IceCreamCompany
            fields = ('name', 'total_trucks', 'total_capacity')

    通过使用Serializer fields我有一个小例子上班.这些字段必须声明为序列化程序的类属性,因此DRF不会在IceCreamCompany模型中抛出不存在的错误.

    转载 http://www.voidcn.com/article/p-fpojmbzo-btw.html

  • 相关阅读:
    安装composer后报错proc_open(): fork failed
    ZOJ4063 Tournament [The 2018 ACM-ICPC Asia Qingdao Regional Contest]
    BZOJ1191: [HNOI2006]超级英雄Hero
    BZOJ1270: [BeijingWc2008]雷涛的小猫
    BZOJ1303 [CQOI2009]中位数图
    BZOJ1192 [HNOI2006]鬼谷子的钱袋
    BZOJ1003 [ZJOI2006]物流运输 最短路+DP
    牛客国庆集训派对Day6 E-Growth
    BZOJ2208 [Jsoi2010]连通数
    BZOJ2761 [JLOI2011]不重复数字
  • 原文地址:https://www.cnblogs.com/catgatp/p/12880047.html
Copyright © 2011-2022 走看看