根据另一个查询集过滤查询集

Rao*_*ufM 3 python django django-queryset

我有一个名为 UserCommunityProfiles 结构如下的模型

class UserCommunityProfile(models.Model):
    owner = models.ForeignKey(
        User,
        on_delete = models.CASCADE)
    (...)
Run Code Online (Sandbox Code Playgroud)

和一个称为订阅结构的模型:

class subscriptions(models.Model):
    subscriber = models.ForeignKey(
        User,
        on_delete = models.CASCADE, related_name='subscriber'
    )
    subscribed_to = models.ForeignKey(
        User,
        on_delete = models.CASCADE, related_name='subscribed_to'
    )
Run Code Online (Sandbox Code Playgroud)

我想要实现的是将不在查询集订阅中的每个用户的个人资料显示为 subscribed_to 并且订阅者是 request.user

我所做的是在我所做的视图中

subs = subscriptions.objects.filter(subscriber=request.user)
profiles = UserCommunityProfile.objects.exclude(owner=subs)
Run Code Online (Sandbox Code Playgroud)

但是我收到一个错误提示Cannot use QuerySet for "subscriptions": Use a QuerySet for "User".我该怎么办?

Wil*_*sem 6

可以使用QuerySets 来过滤其他QuerySets,但正如这里的错误所说,您使用了owners,因此这意味着它希望使用QuerySet包装Users 的 a,但在这里您提供了一个QuerySet包含Subscriptions.

但是,我们可以使用以下查询:

subs = User.objects.filter(subscribed_to__subscriber=request.user)
profiles = UserCommunityProfile.objects.exclude(owner__in=subs)
Run Code Online (Sandbox Code Playgroud)

此外,无论如何我们都不需要两个QuerySets,我们可以这样查询:

profiles = UserCommunityProfile.objects.exclude(
    owner__subscribed_to__subscriber=request.user
)
Run Code Online (Sandbox Code Playgroud)

因此,这将提供一个QuerySet包含所有 UserCommunityProfileS表示其中有没有 Subscriptionsowner作为subscribed_tosubscriber作为self.request.user

如果您像上面演示的那样“组合”查询集,那么通常这将导致单个查询。这通常更有效,因为所有处理都是在数据库级别完成的,并且数据库针对此类任务进行了优化。

然而,在某些情况下可能并非如此,例如,如果一个条件有两个分离条件,并且每个条件都会产生一个(独立的)JOINs的列表,那么最好使用例如 a 重写查询UNION。但这里的情况并非如此。


vip*_*ati 6

解决方案:

subs=User.objects.filter(subscribed_to__subscriber=request.user).values_list('id')
profiles = UserCommunityProfile.objects.exclude(owner__in=subs)
Run Code Online (Sandbox Code Playgroud)