Django 2.1.15自定义排序:点赞数与时间差算法实现求助
Django Review模型自定义评分排序解决方案
嘿,我来帮你搞定这个自定义排序的问题!先梳理下你的场景:
环境信息
- Django版本:2.1.15
- Python版本:3.7.4
- 配置:
settings.py中LANGUAGE_CODE='ko-kr',TIME_ZONE='Asia/Seoul' - Review模型字段:
title、content、movie外键、user外键、like_users多对多字段、created_at和updated_at时间字段
需求
需要按公式 Count(like_users)/(当前时间与created_at的分钟差+60) 降序排序,其中时间差需转为整数分钟。
原代码的问题
你之前的尝试有几个关键问题:
- 直接给
DurationField类型的时间差加整数60——时间间隔和整数不能直接运算,类型不匹配 - 没有计算
like_users的总数量,缺少公式里的分子 - 没有正确计算总分钟差(只算了分钟部分,忽略了小时/天等更长的时间单位)
正确实现代码
from django.db.models import Count, F, ExpressionWrapper, Value from django.db.models.fields import IntegerField, DateTimeField, FloatField, DurationField from django.db.models.functions import ExtractHour, ExtractMinute from django.utils import timezone def test(request): now = timezone.localtime() # 分步计算自定义评分并排序 reviews = Review.objects.annotate( # 1. 计算当前时间与created_at的时间差(时间间隔类型) time_diff=ExpressionWrapper( Value(now, output_field=DateTimeField()) - F('created_at'), output_field=DurationField() ), # 2. 从时间差中提取小时和分钟,计算总分钟数 diff_hours=ExtractHour('time_diff'), diff_minutes=ExtractMinute('time_diff'), total_minutes=ExpressionWrapper( F('diff_hours') * 60 + F('diff_minutes'), output_field=IntegerField() ), # 3. 计算公式的分母:总分钟差 + 60 denominator=ExpressionWrapper( F('total_minutes') + 60, output_field=IntegerField() ), # 4. 计算like_users的总数(分子) like_count=Count('like_users'), # 5. 计算最终评分 score=ExpressionWrapper( F('like_count') / F('denominator'), output_field=FloatField() ) ).order_by('-score') # 按评分降序排序 # 如果需要获取字典形式的数据,可添加.values() # review_data = reviews.values() # 后续逻辑:比如传递给模板渲染 return render(request, 'your_template.html', {'reviews': reviews})
关键说明
- 时间差计算:通过
ExtractHour和ExtractMinute提取时间差的小时和分钟,转换成总分钟数,避免忽略长于1小时的时间间隔 - 类型匹配:所有运算都用
ExpressionWrapper指定输出字段类型,确保数据库层面的运算不会出现类型错误 - 评分计算:先分别算出分子(点赞数)和分母(总分钟差+60),再做除法得到最终评分,最后按
-score降序排序
内容的提问来源于stack exchange,提问作者mmm lee
相关产品推荐
相关产品推荐

