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_from
和 date_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')
我有一个名为 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_from
和 date_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')