我想说,我想按总Threads
,Votes
和Views
订购Comments
。但他们订单模型是从Thread
模型实例化的。
这是我的models.py
class Thread(models.Model):
....
rating = RatingField(can_change_vote=True)
def get_comments(self):
return Comment.objects.filter(thread__pk=self.pk)
def get_visitors(self):
return Visitor.objects.filter(thread__pk=self.pk)
def get_rating_frequence(self):
return self.rating.get_difference()
class Comment(models.Model):
thread = models.ForeignKey(Thread, ...)
....
class Visitor(models.Model):
thread = models.ForeignKey(Thread, ...)
....
以及使用django updown
的Vote
模型
更多信息:https://github.com/weluse/django-updown/blob/master/updown/models.py#L20
class Vote(models.Model):
content_type = models.ForeignKey(ContentType, related_name="updown_votes")
object_id = models.PositiveIntegerField()
....
这是我的views.py
def threads(request):
....
template_name = 'foo/bar/threads.html'
threads = Thread.objects.published()
get_sorted_ratings = request.GET.get('sr', '')
get_sorted_visitors = request.GET.get('sv', '')
get_sorted_comments = request.GET.get('sc', '')
context = {
'threads': threads,
....
}
return render(request, template_name, context)
问题是,如何根据Thread
模型订购多个模型?
在我的测试中:
>>> from django.db.models import (Q, Count, Sum)
>>> from myapp.models import (Thread, Comment, Visitor)
>>> t = Thread.objects.published()
>>> Visitor.objects.filter(thread__in=t).values('thread').annotate(visit=Count('thread__id')).order_by('-visit')
<QuerySet [{'thread': 3, 'visit': 8}, {'thread': 10, 'visit': 8}, {'thread': 9, 'visit': 7}, {'thread': 48, 'visit': 1}, {'thread': 57, 'visit': 1}, {'thread': 79, 'visit': 1}, {'thread': 103, 'visit': 1}, {'thread': 104, 'visit': 1}, {'thread': 132, 'visit': 1}, {'thread': 178, 'visit': 1}, {'thread': 216, 'visit': 1}, {'thread': 227, 'visit': 1}, {'thread': 267, 'visit': 1}, {'thread': 292, 'visit': 1}, {'thread': 300, 'visit': 1}, {'thread': 305, 'visit': 1}, {'thread': 1201, 'visit': 1}, {'thread': 1252, 'visit': 1}, {'thread': 1265, 'visit': 1}, {'thread': 1929, 'visit': 1}]>
>>>
>>> Comment.objects.filter(thread__in=t).values('thread').annotate(total=Count('thread__id')).order_by('-total')
<QuerySet [{'total': 9, 'thread': 10}, {'total': 7, 'thread': 9}, {'total': 3, 'thread': 3}, {'total': 3, 'thread': 213}, {'total': 2, 'thread': 35}, {'total': 2, 'thread': 47}, {'total': 2, 'thread': 104}, {'total': 2, 'thread': 187}, {'total': 2, 'thread': 233}, {'total': 2, 'thread': 235}, {'total': 2, 'thread': 304}, {'total': 1, 'thread': 34}, {'total': 1, 'thread': 68}, {'total': 1, 'thread': 82}, {'total': 1, 'thread': 95}, {'total': 1, 'thread': 137}, {'total': 1, 'thread': 216}, {'total': 1, 'thread': 231}, {'total': 1, 'thread': 244}, {'total': 1, 'thread': 253}, '...(remaining elements truncated)...']>
>>>
>>> # rating likes, id=thread.id, total=total rating
>>> t.values('id').annotate(total=Sum('rating_likes')).order_by('-total')
<QuerySet [{'total': 3, 'id': 10}, {'total': 2, 'id': 104}, {'total': 2, 'id': 233}, {'total': 2, 'id': 235}, {'total': 2, 'id': 304}, {'total': 1, 'id': 3}, {'total': 1, 'id': 9}, {'total': 1, 'id': 34}, {'total': 1, 'id': 35}, {'total': 1, 'id': 47}, {'total': 1, 'id': 68}, {'total': 1, 'id': 82}, {'total': 1, 'id': 95}, {'total': 1, 'id': 137}, {'total': 1, 'id': 187}, {'total': 1, 'id': 213}, {'total': 1, 'id': 216}, {'total': 1, 'id': 231}, {'total': 1, 'id': 244}, {'total': 1, 'id': 253}, '...(remaining elements truncated)...']>
>>>
>>> # rating dislikes, id=thread.id, total=total rating
>>> t.values('id').annotate(total=Sum('rating_dislikes')).order_by('-total')
<QuerySet [{'total': 2, 'id': 3}, {'total': 1, 'id': 9}, {'total': 1, 'id': 10}, {'total': 1, 'id': 35}, {'total': 1, 'id': 47}, {'total': 1, 'id': 187}, {'total': 0, 'id': 29}, {'total': 0, 'id': 34}, {'total': 0, 'id': 42}, {'total': 0, 'id': 45}, {'total': 0, 'id': 48}, {'total': 0, 'id': 51}, {'total': 0, 'id': 53}, {'total': 0, 'id': 57}, {'total': 0, 'id': 68}, {'total': 0, 'id': 72}, {'total': 0, 'id': 75}, {'total': 0, 'id': 76}, {'total': 0, 'id': 77}, {'total': 0, 'id': 79}, '...(remaining elements truncated)...']>
>>>
>>> Thread.objects.get(pk=3).rating.dislikes
2
>>> Thread.objects.get(pk=9).rating.dislikes
1
>>>
最后,我对其进行了更新:,我的代码运行良好,正如@ prakhar-trivedi在https://stackoverflow.com/a/41775990/6396981已经建议的那样
threads = Thread.objects.published()
def sorted_threads(values, order_by='-total', next_order=None):
"""
return sorted threads from values by `order_by`
:param `values`, an example:
values = Comment.objects.filter(thread__in=threads)
.values('thread').annotate(total=Count('thread__id'))
"""
if next_order is not None:
top_values = values.order_by(order_by).order_by(next_order)
else:
top_values = values.order_by(order_by)
list_pk_threads = [pk['thread'] for pk in top_values]
filter_threads = list(threads.filter(pk__in=list_pk_threads))
return sorted(filter_threads, key=lambda i: list_pk_threads.index(i.pk))
在此gist找到完整的内容。
但是 ,我根本不知道如何将其合并。
例如: 从
votes=1
,views=1
,comments=1
开始排序。 结果就是;从 投票 开始按 投票 排序的主题对象,以及 观看次数 以及来自 评论 的热门作品。另一个例子: 从
votes=1
views=1
订购。 此条件的输出应返回仅 投票 受欢迎的主题对象,并且 views < / EM>
1
为True
,-1
为False
答案 0 :(得分:3)
您可以使用 order_by(&#39; -thread&#39;),如下所示:
Comment.objects.filter(thread__in=t).values('thread').annotate(total=Count('thread__id')).order_by('-thread')
如果您想通过评分 主题模型订购记录,您可以使用双下划线&#34; __&#34;在外键查找的线程键上, 像这样:
# rating likes
Comment.objects.filter(thread__in=t).values('thread').annotate(total=Count('thread__id')).order_by('thread__rating_likes')
根据要求在所有查询中使用此功能。