Django 查询,外键不同

Django Query, distinct on foreign key

给定这些模型

class User(Model):
  pass

class Post(Model):
  by = ForeignKey(User) 
  posted_on = models.DateTimeField(auto_now=True)

我想获取最新的 Posts,但不是全部来自同一个 User,我有这样的东西:

posts = Post.objects.filter(public=True) \
        .order_by('posted_on') \
        .distinct("by") 

但是 distinct 在 mysql 上不起作用,我想知道是否有其他方法可以做到这一点? 我看到一些使用 values(),但是 values 对我不起作用,因为我需要对对象本身做更多的事情

order_by 应该匹配 distinct()。在你的情况下,你应该这样做:

posts = Post.objects.filter(public=True) \
        .order_by('by') \
        .distinct('by') 

.distinct([*fields]) 仅适用于 PostgresSQL。

用于 MySql 引擎。这是 Django 中的 MySQL 文档:

Here's the difference. For a normal distinct() call, the database compares each field in each row when determining which rows are distinct. For a distinct() call with specified field names, the database will only compare the specified field names.

对于 MySql 解决方法可能是这样的:

from django.db.models import Subquery, OuterRef


user_post = Post.objects.filter(user_id=OuterRef('id')).order_by('posted_on')            
post_ids = User.objects.filter(related_posts__isnull=False).annotate(post=Subquery(user_post.values_list('id', flat=True)[:1]))).values_list('post', flat=True)
posts = Post.objects.filter(id__in=post_ids)

由于 distinct 在其他字段上不能与 MySQL 一起使用,然后是模型 id,因此可以使用 Subquery:

from django.db.models import Subquery, OuterRef
...
sub_qs = Post.objects.filter(user_id=OuterRef('id')).order_by('posted_on')
# here you get users with annotated last post
qs = User.objects.annotate(last_post=Subquery(sub_qs[:1]))
# next you can limit the number of users

另请注意,posted_on 字段的排序取决于您的模型限制 - 也许您需要将其更改为 -posted_on 以便从最新的开始排序。