通过foreignkey字段排序对象而不是foreignkey计数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过foreignkey字段排序对象而不是foreignkey计数相关的知识,希望对你有一定的参考价值。

我正在为请求提出请求和投票功能:

class Request(models.Model):
    title = models.CharField(max_length=255)
    approved = models.BooleanField(default=False)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

class Vote(models.Model):
    request = models.ForeignKey(Request, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    vote_type = models.BooleanField()

我想通过为每个请求减去不同的vote_type(True / False)来按降序排列总投票数。意味着具有最高票数和最低票数的请求。

我可以这样通过投票订购:

Request.objects.order_by('-vote')

但这只是给了我哪个请求具有最多的外键数,而不是实际的投票数。

我可以获得这样的请求的实际投票计数:

def get_vote_count(obj):
    return obj.vote_set.filter(vote_type=True).count() - obj.vote_set.filter(vote_type=False).count()

但是在获取所有请求并在视图中对它们进行排序时,我无法弄清楚如何实现这一点。

答案

我认为你可以通过使用conditional expressions实现它。

试试这个:

from django.db import models

Request.objects.annotate(
    num_of_true_vote_type=models.Count(
        models.Case(When(vote__vote_type=True, then=1), output_field=models.IntegerField())
    ),
    num_of_false_vote_type=models.Count(
        models.Case(When(vote__vote_type=False, then=1), output_field=models.IntegerField())
    ),
    difference=models.F('num_of_true_vote_type') - models.F('num_of_false_vote_type')
).order_by('-difference')
另一答案

你可以使用aggregation

r = Request.objects.filter(approved=True, vote__vote_type=True).annotate(total_vote=Count('vote'))

这将给你QuerySet Requestapproved=Trueannotate部分将给你额外的atazut total_vote到每个Request对象与所有相关的Votevote_type=True的值计数。

不要忘记它的QuerySet所以,看看有多少Votevote_type=True为“第一”Request你做r.first().total_vote

以上是关于通过foreignkey字段排序对象而不是foreignkey计数的主要内容,如果未能解决你的问题,请参考以下文章

MySQL数据库(25):外键 foreing key

DJango REST Framework 只读字段

排序 JSON 对象

如何在 Django Admin 中更改 ForeignKey 显示文本?

Django模板按“不相关”模型的字段排序

当我使用 Graphene 在 Django GraphQL API 中获取对象时,如何限制 ForeignKey 字段的项目数?