DRF 获取按天分组的好恶

DRF Get likes and dislikes grouped by day

我有一个名为 Post 和 Like 的模型。我怎样才能得到 json 按日期分组的喜欢和不喜欢的数量(Like 模型中的日期字段)?

这是我的models.py

class Post(models.Model):
    """Post model"""
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title


class Like(models.Model):
    """Like model"""
    LIKE = (
        ('like', 'like'),
        ('dislike', 'dislike')
    )

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes')
    like = models.CharField(max_length=255, choices=LIKE)
    date = models.DateField(auto_now=True)

这是我的 serializers.py:

class AnaliticsSerializer(serializers.ModelSerializer):
    """Like analitic"""

    class Meta:
        model = Like
        fields = '__all__'

这是我的 vievs.py:

class AnaliticView(ListAPIView):
    queryset = Like.objects.all()
    serializer_class = AnaliticsSerializer
    filter_backends = [DjangoFilterBackend]
    filter_fields = ['date']

结果如我所愿

[
  {
    "date": "2020-11-14",
    "total_likes": 25,
    "total_dislikes": 17
  },
  {
    "date": "2020-11-15",
    "total_likes": 38,
    "total_dislikes": 8
  },
  {
    "date": "2020-11-18",
    "total_likes": 11,
    "total_dislikes": 0
  }

这是一个基本方法的工作示例。它应该给你想法。

分析代码不应该出现在视图中。此外,一些分组和计数可能会被卸载到数据库,使用像 this.

这样的高级 ORM 查询

views.py

from collections import Counter
from datetime import datetime, timedelta
from itertools import groupby

from django_filters import rest_framework as filters
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from likes.filters import DateRangeFilterSet
from likes.models import Like


class AnaliticView(GenericAPIView):
    queryset = Like.objects.all()
    filter_backends = (filters.DjangoFilterBackend,)
    filterset_class = DateRangeFilterSet

    def get(self, request, format=None):
        queryset = self.get_queryset()
        filtered_queryset = self.filter_queryset(queryset)

        # Queryset needs to be ordered by date for groupby to work correctly
        ordered_queryset = filtered_queryset.order_by('date')
        likes_by_date = groupby(ordered_queryset,
                                lambda like: like.date.strftime("%Y-%m-%d"))

        analytics = []
        for date, likes in likes_by_date:
            count = Counter(like.like for like in likes)
            analytics.append(
                {
                    'date': date,
                    'total_likes': count['like'],
                    'total_dislikes': count['dislike'],

                }
            )

        return Response(analytics)                                  

就像我在评论中所说的那样,可以创建一个轻量级的 class 具有日期和两个总计的属性,并将其实例列表传递给序列化程序以获取响应数据.在我看来,这太过分了,因为您可以构建一个可以轻松序列化为 JSON.

的字典

更新:

我已经切换到 GenericAPIView,它是 ListAPIView 的超级class,因为它支持过滤器后端。我添加了一个 FilterSet 过滤 date_fromdate_to:

filters.py

from django_filters import rest_framework as filters

from likes import models


class DateRangeFilterSet(filters.FilterSet):
    date_from = filters.DateFilter(field_name='date', lookup_expr='gte')
    date_to = filters.DateFilter(field_name='date', lookup_expr='lte')

    class Meta:
        model = models.Like
        fields = ('date_from', 'date_to')