Django拆分字典格式queryset 实现博客日期与点赞数表格展示
解决方案
问题梳理
现有代码核心问题有三点:
Likes模型未存储点赞发生时间,只能获取关联博客的发布时间,无法统计博客发布后每日的点赞数据- 视图中的查询过滤条件错误,只能筛选出与博客发布时间完全一致的点赞记录
- 遍历
Counter类型结果时只遍历了键,没有获取对应点赞数值
步骤1:修正模型
给Likes表新增点赞时间字段,记录点赞发生的时间:
# models.py class BlogPost(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=30, default='') date = models.DateTimeField(auto_now_add=True) class Likes(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) blogpost_like = models.ForeignKey(BlogPost, on_delete=models.CASCADE) like_date = models.DateTimeField(auto_now_add=True) # 新增点赞时间字段
修改完成后执行迁移命令生效:python manage.py makemigrationspython manage.py migrate
步骤2:修正视图逻辑
重新构造查询逻辑,按点赞日期分组统计,同时格式化日期输出格式:
# views.py from django.shortcuts import get_object_or_404, render from django.db.models import Count from django.db.models.functions import ExtractDay, ExtractMonth def page(request, pk): # 补充缺失的pk参数 blogpost = get_object_or_404(BlogPost, pk=pk) # 按点赞日期的日、月分组,统计每日点赞数 totals = blogpost.likes_set.annotate( like_day=ExtractDay('like_date'), like_month=ExtractMonth('like_date') ).values('like_day', 'like_month').annotate( likes_count=Count('pk') ).order_by('like_month', 'like_day') # 构造模板所需的结构化数据 month_map = {1: 'Jan.', 2: 'Feb.', 3: 'Mar.', 4: 'Apr.', 5: 'May', 6: 'Jun.', 7: 'Jul.', 8: 'Aug.', 9: 'Sep.', 10: 'Oct.', 11: 'Nov.', 12: 'Dec.'} result_list = [] for item in totals: result_list.append({ 'blog_date': f"{item['like_day']} {month_map[item['like_month']]}", 'likes': f"{item['likes_count']} Likes" }) context = {'result_list': result_list} return render(request, 'page.html', context)
步骤3:模板渲染表格
在page.html中直接遍历数据渲染即可:
<table> <thead> <tr> <th>Blog Date</th> <th>Likes</th> </tr> </thead> <tbody> {% for item in result_list %} <tr> <td>{{ item.blog_date }}</td> <td>{{ item.likes }}</td> </tr> {% endfor %} </tbody> </table>
临时兼容方案(无需修改模型)
如果仅需要统计博客发布当日的点赞数据,不需要新增Likes表字段,可以直接修正结果处理逻辑:
# views.py 中替换结果处理部分 from collections import Counter def page(request, pk): blogpost = get_object_or_404(BlogPost,pk=pk) totals = blogpost.likes_set.filter( blogpost_like__date=blogpost.date, ).annotate( date=ExtractDay('blogpost__date'), ).values( 'date' ).annotate( n=Count('pk') ).order_by('date').values() results = Counter({d['date']: d['n'] for d in totals}) # 修正结果处理逻辑 month_map = {1: 'Jan.', 2: 'Feb.', 3: 'Mar.', 4: 'Apr.', 5: 'May', 6: 'Jun.', 7: 'Jul.', 8: 'Aug.', 9: 'Sep.', 10: 'Oct.', 11: 'Nov.', 12: 'Dec.'} result_list = [] post_month = blogpost.date.month # 遍历Counter的键值对,而非仅遍历键 for day, count in results.items(): result_list.append({ 'blog_date': f"{day} {month_map[post_month]}", 'likes': f"{count} Likes" }) context = {'result_list': result_list} return render(request, 'page.html', context)
内容的提问来源于stack exchange,提问作者user16963356
相关产品推荐
相关产品推荐

