Reputation: 11935
I have a list and I would to remove from it all elements that are contained into an other list.
So, I would to have something like to 'exclude
' queryset but on a list.
Now this is my code:
list = Friend.objects.friends(self.request.user)
i_am_blocking = User.objects.filter(blocks_received__user_blocking=self.request.user)
is_blocking_me = User.objects.filter(blocks_set__user_blocked=self.request.user)
blocked_users = list(chain(i_am_blocking, is_blocking_me))
and now I would to remove from 'list
' all items that are contained into 'blocked_users
'.
Is there a better way to make this?
Upvotes: 0
Views: 6337
Reputation: 53669
A slightly more optimized version:
friend_list = Friend.objects.friends(self.request.user)
i_am_blocking = User.objects.filter(...).values_list('pk', flat=True)
is_blocking_me = User.objects.filter(...).values_list('pk', flat=True)
blocked_users = set(chain(i_am_blocking, is_blocking_me))
friend_list = [friend for friend in friend_list if friend.user_id not in blocked_users]
This has two main advantages. First, blocked_users
is a set
, so user not in blocked_users
doesn't have to loop through all blocked users to determine if the condition is true or not. Secondly, by getting a list of pk
's, and comparing to friend.user_id
, you avoid an extra query for each possible friend: user_id
is a local field on friend
, while user
is an accessor that fetches the whole user
object from the database.
The most efficient would still be to filter at the ORM level. Btw, please don't assign anything to list
. It shadows the built-in list()
type, if necessary you can use list_
, but it's generally better to use a more descriptive name.
Upvotes: 0
Reputation: 45575
You can use the list comprehension:
list = [friend for friend in list if friend.user not in blocked_users]
UPDATE: to do the same at ORM level you can use query like this:
list = Friend.objects.friends(self.request.user) \
.exclude(user__in=blocked_users)
Upvotes: 5