2015-05-07 2 views
0

У меня есть список, и я должен удалить из него все элементы, которые содержатся в другом списке.Django, функция exclude() в списке

Итак, у меня было бы что-то вроде 'exclude' queryset, но в списке.

Теперь это мой код:

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

и теперь я хотел бы, чтобы удалить из «list» всех элементов, которые содержатся в «blocked_users».

Есть ли лучший способ сделать это?

ответ

2

Вы можете использовать список понимание:

list = [friend for friend in list if friend.user not in blocked_users] 

UPDATE: сделать то же самое на уровне ORM вы можете использовать запрос, как это:

list = Friend.objects.friends(self.request.user) \ 
        .exclude(user__in=blocked_users) 
+0

хорошо, это хорошо работает. Как вы думаете, это хороший способ (эффективный) сделать это? Вы видите улучшения? – Safari

+0

Это зависит от количества firends и заблокированных пользователей. Вы должны проверить его самостоятельно. Я добавил альтернативное решение на основе ORM для ответа. Это может быть более эффективным, чем манипулирование данными в python. – catavaran

+0

Спасибо за ваше обновление. Невозможно использовать .exclude, потому что Friend.objects.friends (self.request.user) возвращает «список», а не набор запросов. Итак, я получу ошибку, подобную этой: объект «list» не имеет атрибута «exclude» – Safari

0

чуть более оптимизированной версии:

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] 

Это имеет два основных преимущества. Во-первых, blocked_users является set, поэтому user not in blocked_users не нужно перебирать всех заблокированных пользователей, чтобы определить, является ли условие истинным или нет. Во-вторых, получив список pk и сравнивая с friend.user_id, вы избегаете дополнительного запроса для каждого возможного друга: user_id - это локальное поле на friend, а user - это аксессор, который извлекает весь объект user из базы данных.

Наиболее эффективным будет фильтрация на уровне ORM. Btw, пожалуйста, не присваивайте ничего list. Он затеняет встроенный тип list(), при необходимости вы можете использовать list_, но обычно лучше использовать более описательное имя.