【问题标题】:select latest comments for multiple objects at once一次选择多个对象的最新评论
【发布时间】:2011-12-14 18:33:03
【问题描述】:

假设我有一个这样的评论模型:

class Comment(models.Model):
    user = models.ForeignKey(User)
    content = models.CharField(max_length=200)
    create_time = models.DateTimeField(blank=True, default=datetime.datetime.now)

    content_type = models.ForeignKey(ContentType, verbose_name=_('content type'))
    object_id    = models.PositiveIntegerField(_('object id'), db_index=True)
    object       = generic.GenericForeignKey('content_type', 'object_id')

如果我可以在一个查询中为同一 content_type 中的多个对象(比如帖子,提供这些帖子的 id)选择最新的几个 cmets?

如果可能的话,如何在一个查询中为这些对象选择最旧的评论和最新的 4 个 cmets?

谢谢!

【问题讨论】:

    标签: django django-queryset django-contenttypes


    【解决方案1】:

    您提到“提供这些帖子的 ID”,但实际上没有定义任何 Post 模型(至少在您的问题中)。但是,由于您要求使用相同的content_type 获取所有 cmets,我不确定如何需要这些帖子。

    以下查询获取与 ContentType 与某个主键 (1) 匹配的所有 Comment 项目,按 create_time 对它们进行排序并选择前 4 个项目:

    Comment.objects.filter(content_type__pk=1).order_by('-create_time')[:4]
    

    【讨论】:

    • Post 是什么样的并不重要。给 Post 的 content_type_pk 为 1,Posts id 为 [1,2,3,4],那么这四个 Post 的所有评论都是 Comment.objects.filter(content_type__pk=1, object_id__in=[1,2,3,4 ],我的问题是如何为所有四个帖子获取最新的四个 cmets。
    【解决方案2】:

    我遇到了greatest-n-per-group 问题。我不得不使用原始 SQL 来获得我的结果(我的常见问题解答中每个问题类别的前 X 个问题)。没有简单的方法可以通过 ORM 做到这一点。

    这篇文章:使用一个有趣的 SQL 解决方案 SQL join: selecting the last records in a one-to-many relationship

    我的解决方案涉及子查询。由于您使用的是通用键,因此可能会涉及更多的挠头。

    我最终只是回到了 ORM,并在这个特定视图上进行了积极的缓存,所以我可能会建议这样做。跟上 SQL 实在是太痛苦了。

    Foo.objects.raw('''
        SELECT ...
        FROM foo
        LEFT OUTER JOIN bar
        ON (foo.bar_id = bar.id ) 
        WHERE foo.id
        IN (
            SELECT subquery.id 
            FROM foo subquery 
            WHERE foo.bar_id = subquery.bar_id
            ORDER BY score DESC
            LIMIT %s
            )
        ORDER BY "baz" DESC;''', [5])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2012-01-17
      • 2015-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多