【问题标题】:Django Query: How to order posts by amount of upvotes?Django Query:如何按赞数排序帖子?
【发布时间】:2019-05-17 01:27:09
【问题描述】:

我目前正在开发一个网站(使用 Django),人们可以在该网站上写一个故事,该故事可以由他们自己或其他人点赞。以下是 Profile、Story 和 Upvote 的类:

class Profile(AbstractBaseUser, PermissionsMixin):
  email = models.EmailField(unique=True)
  first_name = models.CharField(max_length=30, null=True)
  last_name = models.CharField(max_length=30, null=True)


class Story(models.Model):
  author = models.ForeignKey('accounts.Profile', on_delete=models.CASCADE, related_name="author")
  title = models.CharField(max_length=50)
  content = models.TextField(max_length=10000)


class Upvote(models.Model):
  profile = models.ForeignKey('accounts.Profile', on_delete=models.CASCADE, related_name="upvoter")
  story = models.ForeignKey('Story', on_delete=models.CASCADE, related_name="upvoted_story")
  upvote_time = models.DateTimeField(auto_now=True)

如您所见,Upvote 使用两个外键来存储支持者和相关故事。现在我想做一个查询,它给我所有的故事,按他们拥有的赞成票的数量排序。我已经尽力自己提出了一些问题,但这并不是我要搜索的内容。

这个根本不起作用,因为它只是按照它们的创建顺序给了我所有的故事,出于某种原因。它还包含重复项,尽管我希望它们按故事分组。

hot_feed = Upvote.objects.annotate(upvote_count=Count('story')).order_by('-upvote_count')

这种作品。但是,如果我试图访问我的模板中的一个特定故事,它只会给我返回 id。所以我无法从那个 id 中获取标题、作者和内容,因为它只是一个整数,而不是一个对象。

hot_feed = Upvote.objects.values('story').annotate(upvote_count=Count('story')).order_by('-upvote_count')

有人可以帮我找到我正在搜索的查询吗?

【问题讨论】:

  • 请删除所有与此问题无关的字段(我们希望有最小示例)。
  • 会的!谢谢

标签: django django-models django-templates django-views django-queryset


【解决方案1】:

你从错误的模型中查询,你这里基本上是按故事数量或类似的东西来获取Upvotes。

但是你的宝宝想通过点赞数来检索Storys,所以你需要使用Story作为“查询集根”,并用点赞数对其进行注释:

Story.objects.annotate(
    upvote_count=Count('upvoted_story')
).order_by('-upvote_count')

我认为您的story 中的related_name 有点“误导”。 related_name 是“反向”关系的名称,所以可能更好的名称是 upvotes

class Upvote(models.Model):
    profile = models.ForeignKey(
        'accounts.Profile',
        on_delete=models.CASCADE,
        related_name='upvotes'
    )
    story = models.ForeignKey(
        'Story',
        on_delete=models.CASCADE,
        related_name='upvotes'
    )
    upvote_time = models.DateTimeField(auto_now=True)

在这种情况下,查询是:

Story.objects.annotate(
    upvote_count=Count('upvotes')
).order_by('-upvote_count')

【讨论】:

  • 我一定很困惑我应该为 Upvotes 还是 Stories 获取信息。无论如何,这行得通!你真的帮了我很多,非常感谢!不过我还有一个问题,如果你不介意的话。在该查询中,您计算​​“upvoted_story”,但它如何知道故事是否被赞成,因为它存储在不同的模型中?然后最后你通过'upvote_count'订购。它从哪里获得这些信息?
  • 哦,不,我明白了。您使用related_name 来构建查询,对吧?
  • @FrederikVanclooster: 'upvoted_story'ForeignKeyrelated_name,因此它将在数据库中执行JOINGROUP BY,并计算相关赞成票。我们将该计数存储为upvote_count(这是.annotate(..)= 之前的部分。因此这是一个整数,我们按降序对其进行排序。
  • 是的,我现在明白了!非常感谢:)
  • @FrederikVanclooster:确实。它使用ForeignKey 的名称。
猜你喜欢
  • 1970-01-01
  • 2017-08-31
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
相关资源
最近更新 更多