我想创建一个趋势帖子的公式。到目前为止,我已经做到了:
def hot(request):
posts = Post.objects.all()
for post in posts:
likes = int(post.likes)
views = int(post.blog_view)
rep = int(post.author.profile.reputation)
d0 = timezone.now()
d1 = post.date_posted
days = (d0 - d1).days
trending_score = (3/(1+days**(1/3)))*(0.5*views+0.25*rep+2.5*likes)
该公式处于trending_score变量,每次它都会返回其趋势得分的数字。trending_score越高,趋势性越强。
现在我想使用order_by或其他东西在django中实现这一点:
def hot(request):
posts = Post.objects.all()
for post in posts:
likes = int(post.likes)
views = int(post.blog_view)
rep = int(post.author.profile.reputation)
d0 = timezone.now()
d1 = post.date_posted
days = (d0 - d1).days
trending_score = (3/(1+days**(1/3)))*(0.5*views+0.25*rep+2.5*likes)
context = {
Post.objects.all().order_by(-trending_score)
}
return render(request, 'blog/popularity.html', context)
我显然知道这不会起作用,因为我把trending_score放在for循环中,上下文在它之外,所以它不会起作用。错误是:Invalid order_by arguments: [-21.75]
但我不知道还能怎么做。如有任何帮助,我们将不胜感激。
您可以用公式计算的值对查询集进行注释,然后根据注释对其进行排序。最重要的是将您的公式转换为django-ORM所理解的表示形式,以便将其转换为正确的SQL语句。像这样的东西应该起作用:
from django.db.models import F, FloatField, DurationField
from django.db.models.functions import Cast, Now, Extract
days = Cast(
Extract(Cast(Now() - F('date_posted'), DurationField()), 'days'),
FloatField()
)
views = Cast('views', FloatField())
rep = Cast('post.author.profile.reputation', FloatField())
likes = Cast('likes', FloatField())
Post.objects.all().annotate(
trending_score=(3./(1+days**(1/3)))*(.5*views+.25*rep+2.5*likes)
).order_by('-trending_score')
我能想到的最简单的修复方法是创建一个新的列表来存储结果。这将允许您在不必更改模型或任何内容的情况下,按特定属性排序结果。
def hot(request):
posts = Post.objects.all()
result = []
for post in posts:
likes = int(post.likes)
views = int(post.blog_view)
rep = int(post.author.profile.reputation)
d0 = timezone.now()
d1 = post.date_posted
days = (d0 - d1).days
trending_score = (3/(1+days**(1/3)))*(0.5*views+0.25*rep+2.5*likes)
result.append((trending_score, post)) #added a tuple of value-object
context = {
sorted(result, reverse=True)
}
return render(request, 'blog/popularity.html', context)
在HTML页面上,而不是
{% for post in posts %}
你可以使用
{% for object in posts %}
post = object[1]