如何使用count()获取特定日期之间的项目

1 投票
1 回答
32 浏览
提问于 2025-04-14 18:09

通过这段代码,我可以获取所有与Article相关的orders项目,但这里有个问题,我想要获取在两个日期之间的orders数量,这两个日期是根据指定的timestamp来确定的。我该怎么做呢?


class Order(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    author = models.ForeignKey(User,  on_delete=models.CASCADE,related_name='ordersauthor')
    article = models.ForeignKey(Article, null=True, blank=True, on_delete=models.CASCADE,related_name='ordersarticle')
    timestamp = models.DateTimeField(auto_now_add=True)
    total_price = models.FloatField(default='0', validators=[MaxValueValidator(99999999999999999999)])

class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.SerializerMethodField(read_only=True)


    class Meta:
        model = Article
        fields = '__all__'

    def get_orders(self, language):
        return language.ordersarticle.count()

初始输出:

{
            .....,
             "orders": 4, // All orders
        },

期望输出:

{
            .....,
             "orders": 1, // Orders between 4th and 11th of march (Example)
        },

更新:

class ArticleViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)
    queryset = Article.objects.all().order_by('-timestamp')
    serializer_class = ArticleSerializer
    filter_backends = [filters.SearchFilter,DjangoFilterBackend]
    pagination_class = StandardResultsSetPagination
    search_fields = ['^articlechoices__item','^caption','^name']
    filterset_fields = ['author','price','location','category']

1 个回答

1

你可以使用以下方式进行筛选:

from datetime import date


class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Article
        fields = '__all__'

    def get_orders(self, language):
        return language.ordersarticle.filter(
            timestamp__range=(date(2024, 3, 4), date(2024, 3, 7))
        ).count()

不过,这样做其实不太好:如果你需要序列化多个这样的Article,那么每个项目都会产生一个查询。

我们可以提前计算这些内容,方法是:

from django.db.models import Count, Q


class ArticleViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)
    queryset = Article.objects.all().order_by('-timestamp')
    serializer_class = ArticleSerializer
    filter_backends = [filters.SearchFilter, DjangoFilterBackend]
    pagination_class = StandardResultsSetPagination
    search_fields = ['^articlechoices__item', '^caption', '^name']
    filterset_fields = ['author', 'price', 'location', 'category']

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .annotate(
                num_orders=Count(
                    'ordersarticle',
                    filter=Q(
                        ordersarticle__timestamp__range=(date(2024, 3, 4), date(2024, 3, 7))
                    ),
                )
            )
        )

然后可以用以下方式进行序列化:

class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.IntegerField(read_only=True, source='num_orders')

    class Meta:
        model = Article
        fields = '__all__'

注意:通常来说,使用 settings.AUTH_USER_MODEL [Django-doc] 来引用用户模型,比直接使用 User 模型 [Django-doc] 更好。想了解更多信息,可以查看文档中的 引用 User 模型 部分


注意related_name=… 参数 [Django-doc] 是反向关系的名称,也就是说,从 User 模型到 Order 模型。在这种情况下,给它起个和正向关系一样的名字通常没有太大意义。所以你可能想考虑把 ordersauthor 这个关系改名为 orders

撰写回答