【问题标题】:Write an Effective query for django for a FOR Loop?为 django 编写一个 FOR 循环的有效查询?
【发布时间】:2022-01-18 00:40:47
【问题描述】:

我需要从这些模型中获取每个月购买的保单数量

class Insurance(models.Model):
  #other fields..
  date_purchased_on = models.DateField(auto_now_add=True)    
  customer_region = models.CharField(
    max_length=10, choices=RegionType.choices)

所以我写了一个视图来获得响应

@api_view(['GET'])
def chart_data(request):
    # structure of the op should be all the months from 1 to 12
    #  [{"month": 1,"count": 100,}, { "month:2", "count":20}]

    filtered_data = []
    for i in range(1, 13):
        query = Insurance.objects.filter(date_purchased_on__month=i).count()
        data = {
            "month": i,
            "count": query
        }
        filtered_data.append(data)
        
    return Response(filtered_data)

现在问题是这个查询每次都访问数据库大约 12 次。有没有办法处理这个问题以进入一个单个查询或减少它

和我的记录器结果

(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 1; args=(1,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 2; args=(2,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 3; args=(3,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 4; args=(4,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 5; args=(5,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 6; args=(6,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 7; args=(7,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 8; args=(8,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 9; args=(9,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 10; args=(10,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 11; args=(11,); alias=default
(0.000) SELECT COUNT(*) AS "__count" FROM "insurance_insurance" WHERE EXTRACT('month' FROM "insurance_insurance"."date_purchased_on") = 12; args=(12,); alias=default

【问题讨论】:

标签: python django database postgresql


【解决方案1】:

您可以使用ExtractMonth expression [Django-doc] 提取月份并按该月排序:

from django.db.models import Count
from django.db.models.functions import ExtractMonth

Insurance.objects.values(month=ExtractMonth('date_purchased_on')).annotate(
    count=Count('pk')
).order_by('month')

这将产生一个QuerySet 的字典,看起来像:

<QuerySet [
    {'month': 6, 'count': 100 },
    {'month': 7, 'count': 20 }
]>

没有Insurance 对象的月份将包含在QuerySet 中。因此,您可能必须对其进行后处理,并为这些记录包含'count': 0 的记录。

【讨论】:

  • 有没有办法得到每个月购买了多少保单的地区响应? { 'east':[列表中的所有月份数据],'west':[列表中的所有月份数据],'north':[列表中的所有月份数据],'south':[列表中的所有月份数据列表]}
  • 是的,您将'customer_region' 添加为.values(..) 的第一个参数并在.order_by('customer_region', 'month') 中。
  • @Gokulaselvan: 所以Insurance.objects.values('customer_region', month=ExtractMonth('date_purchased_on')).annotate(count=Count('pk')).order_by('customer_region', 'month').
  • @Gokulaselvan:但同样的评论适用:如果该区域-月份组合没有Insurances,它将不包含区域和月份的记录。
猜你喜欢
  • 1970-01-01
  • 2014-04-17
  • 2023-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
  • 2021-11-18
  • 1970-01-01
  • 2015-11-01
相关资源
最近更新 更多