RaoufM
RaoufM

Reputation: 555

filtering a queryset based on another queryset

I have a model called UserCommunityProfiles Structured as follows

class UserCommunityProfile(models.Model):
    owner = models.ForeignKey(
        User,
        on_delete = models.CASCADE)
    (...)

and a model called subscriptions structured :

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'
    )

and what i am trying to achieve is display the profiles of every user which is not in the query set subscriptions as a subscribed_to and the subscriber is request.user

what i did is in the views i did

subs = subscriptions.objects.filter(subscriber=request.user)
profiles = UserCommunityProfile.objects.exclude(owner=subs)

but i get an error saying Cannot use QuerySet for "subscriptions": Use a QuerySet for "User". what should i do ?

Upvotes: 12

Views: 11127

Answers (2)

vipul prajapati
vipul prajapati

Reputation: 293

Solution:

subs=User.objects.filter(subscribed_to__subscriber=request.user).values_list('id')
profiles = UserCommunityProfile.objects.exclude(owner__in=subs)

Upvotes: 18

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

It is possible to use QuerySets to filter other QuerySets, but as the error here says, you use owners, so that means that it expects to work with a QuerySet that wraps Users, but here you provide a QuerySet containing Subscriptions.

We can however use the following query:

subs = User.objects.filter(subscribed_to__subscriber=request.user)
profiles = UserCommunityProfile.objects.exclude(owner__in=subs)

Furthermore we do not need two QuerySets anyway, we can query it like:

profiles = UserCommunityProfile.objects.exclude(
    owner__subscribed_to__subscriber=request.user
)

This will thus provide a QuerySet that contains all UserCommunityProfiles for which there is no Subscriptions with the owner being the subscribed_to and the subscriber being the self.request.user.

If you "combine" querysets like demonstrated above, then typically this will result in a single query. This usually is more efficient, since then all processing is done at the database level, and databases are optimized for such tasks.

There can however be some cases where that is not the case, for example if one has two disjunct conditions, and each conditions results in a list of (independent) JOINs, then it might be better to rewrite the query with for example a UNION. But this is not the case here.

Upvotes: 7

Related Questions