【问题标题】:Django .order_by() with .distinct() using postgresDjango .order_by() 和 .distinct() 使用 postgres
【发布时间】:2012-06-29 02:47:20
【问题描述】:

我有一个与Article 模型相关的Read 模型。我想做的是创建一个查询集,其中文章是唯一的并由date_added 排序。由于我使用的是 postgres,我更喜欢使用 .distinct() 方法并指定 article 字段。像这样:

articles = Read.objects.order_by('article', 'date_added').distinct('article')

但是,这并没有达到预期的效果,并按照创建的顺序对查询集进行排序。我知道 Django 文档中关于 .distinct().order_by() 的注释,但我认为它不适用于这里,因为它提到的副作用是会有重复,我没有看到。

# To actually sort by date added I end up doing this
articles = sorted(articles, key=lambda x: x.date_added, reverse=True)

这会在我真正需要它之前执行整个查询,如果有很多记录,它可能会变得非常慢。我已经使用select_related() 进行了优化。

是否有更好、更有效的方法来创建具有相关模型和 order_by 日期唯一性的查询?

更新 理想情况下,输出将是 Read 实例的查询集,其中它们的相关文章在查询集中是唯一的,并且仅使用 Django orm(即在 python 中排序)。

【问题讨论】:

  • 你运行的是什么版本的 Django?将参数传递给distinct 仅在 1.4+ 中可用
  • 1.4 并使用 postgres,它可以工作

标签: django postgresql


【解决方案1】:

是否有更好、更有效的方法来创建具有相关模型和 order_by 日期唯一性的查询?

可能。没有全貌很难说,但我的假设是您正在使用 Read 来跟踪哪些文章已阅读和未阅读,并且可能将其与 User 实例联系起来以确定特定用户是否已阅读文章或不。如果是这种情况,那么您的方法是有缺陷的。相反,您应该执行以下操作:

class Article(models.Model):
    ...
    read_by = models.ManyToManyField(User, related_name='read_articles')

然后,要获取特定用户的阅读文章,您可以这样做:

user_instance.read_articles.order_by('date_added')

这不需要使用distinct,因为现在不会有任何重复。

更新

要获取至少被一位用户阅读的所有文章:

Article.objects.filter(read_by__isnull=False)

或者,如果你想设置流行度的阈值,你可以使用注解:

from django.db.models import Count

Article.objects.annotate(read_count=Count('read_by')).filter(read_count__gte=10)

这只会为您提供至少被 10 位用户阅读过的文章。

【讨论】:

  • 感谢您的帮助!这个特定的查询实际上是为了关注您所关注的多个用户正在阅读的内容。我省略了执行此操作的另一个过滤器。我需要这个来聚合多个用户,所以在这种情况下,查询 Read 模型而不是 Article 模型似乎更有效。这有意义吗?
  • @ChrisPratt 您在更新的第一个查询中有错字:ready_by
  • 如果您正在寻找该文章,您的答案可以正常工作。不过,我对 Read 实例很感兴趣。所以输出应该是一个 Read 实例的查询集,其文章是唯一的。我不确定 ORM 是否会让我在没有在 python 中而不是 django orm 中进行某种排序的情况下做到这一点。
  • “read”是一个状态,而不是一个实例,也就是说,没有“read”之类的东西。没有任何查询可以作为单独的模型运行,也不能作为Article 上的状态属性运行(实际上更有效)。我的最后一个代码示例为您提供了所有“阅读”文章,所以我不确定您在这里缺少什么,但如果您需要其他任何内容,请给我具体信息,我也会向您展示一个查询。
  • 非常感谢。看起来这是我对数据库模式做出的选择的一个更深层次的问题。将更多地考虑其影响。如果这是 Article 模型上与 User 对象相关的 ManyToMany 字段,它将没有我需要的信息(即读取时间)。如果我要执行与 Read 实例相关的 ManyToMany,我仍然处于同样的难题中。
猜你喜欢
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 2016-12-17
  • 2014-01-02
  • 1970-01-01
  • 2019-08-06
  • 2017-06-01
  • 2017-06-09
相关资源
最近更新 更多