Django 查询,外键不同
Django Query, distinct on foreign key
给定这些模型
class User(Model):
pass
class Post(Model):
by = ForeignKey(User)
posted_on = models.DateTimeField(auto_now=True)
我想获取最新的 Post
s,但不是全部来自同一个 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
以便从最新的开始排序。
给定这些模型
class User(Model):
pass
class Post(Model):
by = ForeignKey(User)
posted_on = models.DateTimeField(auto_now=True)
我想获取最新的 Post
s,但不是全部来自同一个 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
以便从最新的开始排序。