Safari
Safari

Reputation: 11935

Django, exclude() function on list

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

Answers (2)

knbk
knbk

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

catavaran
catavaran

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

Related Questions