Django:如何根据月份过滤 Django 对象?

huangapple go评论58阅读模式
英文:

Django: How to filter django objects based on month?

问题

I will provide a translation of the code and content you provided. Here's the translated code and content:

我正在尝试获取/计算一个月内有多少订单我已经编写了一些逻辑来实现这个目标但问题是它没有统计一个月内有多少总订单而是将不同的订单分散在同一个月中

为了更明确看下面的响应

**查询集的当前外观**

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 1}, {'month': 6, 'count': 1}]>


**期望的查询集应该如下所示**

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 2}]>


`'month': 4` 表示 'month': 四月,`'month': 6` 表示 'month': 六月

这是我编写的用于此目的的代码,但它无法正常工作

models.py

class CartOrder(models.Model):
    vendor = models.ManyToManyField(Vendor)
    ...
    date = models.DateTimeField(auto_now_add=False)

views.py

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

orders = CartOrder.objects.annotate(month=ExtractMonth('date')).values('month').annotate(count=Count('id')).values('month', 'count')

print(orders)

终端输出

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 1}, {'month': 6, 'count': 1}>

Please note that I have translated the code and content you provided. If you have any specific questions or need further assistance, please feel free to ask.

<details>
<summary>英文:</summary>

I am trying to get/count how many orders that were made in a month, i have written some logic to do this, but the issue is this: It does not count how many total orders were made in a month, it spreads different orders on the same month.



To be more explicit, look at the reponse below:

**This is how to the queryset looks now**

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 1}, {'month': 6, 'count': 1}]>

**This is how to the expected queryset should look**

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 2}]>


The `&#39;month&#39;:4` is `&#39;month&#39;:April` and `&#39;month&#39;:6` is `&#39;month&#39;:June`

---
This is the code i have written to do this, but does not work

**models.py**

class CartOrder(models.Model):
vendor = models.ManyToManyField(Vendor)
...
date = models.DateTimeField(auto_now_add=False)


**views.py**

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

orders = CartOrder.objects.annotate(month=ExtractMonth('date')).values('month').annotate(count=Count('id')).values('month','count')

print(orders)


terminal

<QuerySet [{'month': 4, 'count': 1}, {'month': 6, 'count': 1}, {'month': 6, 'count': 1}]>




</details>


# 答案1
**得分**: 1

以两种不同的方式。首先,简单地从您的对象 QuerySet 中选择不同的月份,然后按月份过滤数据集并计算结果:

```python
class ObjectsPerMonthListView(generic.ListView):
    model = CartOrder
    template_name = 'some_template.html'

    def get_queryset(self):
        qs = super().get_queryset()
        months = qs.values('date__month').distinct()
        data = []
        for value in months:
            count = qs.filter(date__month=value['date__month']).count()
            data.append({'month': value['date__month'], 'count': count})

        return data

或者,以更“高级”的方式,我们可以使用 .order_by 来按照不同的值进行分组:

class ObjectsPerMonthListView(generic.ListView):
    model = CartOrder
    template_name = 'some_template.html'

    def get_queryset(self):
        qs = super().get_queryset()
        alternative = (
            qs
            .order_by('id')
            .values('date__month')
            .annotate(count=Count('id'))
            .order_by()
        )

        return alternative

some_template.html

<h2>每月对象数</h2>

{% for obj in object_list %}
    <p>{{ obj }}</p>
{% endfor %}
英文:

In two different ways. First, in a simple way, you can just select distinct months from your object QuerySet, then filter the data set counting results per months:

class ObjectsPerMonthListView(generic.ListView):
    model = CartOrder
    template_name = &#39;some_template.html&#39;

    def get_queryset(self):
        qs = super().get_queryset()
        months = qs.values(&#39;date__month&#39;).distinct()
        data = []
        for value in months:
            count = qs.filter(date__month=value[&#39;date__month&#39;]).count()
            data.append({&#39;month&#39;: value[&#39;date__month&#39;], &#39;count&#39;: count})

        return data

Alternatively, in a more "advanced" way, we can use .order_by to group by distinct values:

class ObjectsPerMonthListView(generic.ListView):
    model = CartOrder
    template_name = &#39;some_template.html&#39;

    def get_queryset(self):
        qs = super().get_queryset()
        alternative = (
            qs
            .order_by(&#39;id&#39;)
            .values(&#39;date__month&#39;)
            .annotate(count=Count(&#39;id&#39;))
            .order_by()
        )

        return alternative

some_template.html

&lt;h2&gt;Objects Per Month&lt;/h2&gt;

{% for obj in object_list %}
    &lt;p&gt;{{ obj }}&lt;/p&gt;
{% endfor %}

huangapple
  • 本文由 发表于 2023年4月6日 21:38:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75950196.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定