Django queryset filter by list - получение элементов списка, которые не найдены
Допустим, есть модель django Data
с полем символов hash
и списком хэшей all_hashes
. Теперь понятно, что можно использовать выражение фильтрации для получения всех объектов в Data
, которые находятся внутри списка хэшей, используя синтаксис __in
, например:
all_hashes = ['45df...','ab23...', ... ]
filtered_data = Data.objects.filter(hash__in=all_hashes)
Таким образом, если кто-то хочет узнать, какие хэши были найдены, можно просто сделать
filtered_hashes = [obj.hash for obj in filtered_data]
И вы можете получить хэши, которые не были найдены, как
new_hashes = set(all_hashes) - set(filtered_hashes)
Конечно, вы также можете напрямую получить new_hashes
, проходя один за другим по списку all_hashes
и по отдельности пытаясь получить соответствующий объект из базы данных, однако это похоже на то, что это вызовет много запросов и этого следует избегать.
Вопрос в том, есть ли более прямой способ определить, для каких элементов списка не удалось найти подходящий объект - возможно, что-то вроде:
objects_existing = Data.objects.exist(hash__in=all_hashes) => [true, false, ...]
В качестве возможного решения, попробуйте:
objects_existing = Data.objects.annotate(hash_in_all_hashes=Exists(Data.objects.filter(id=OuterRef('id'), hash__in=all_hashes)))
Теперь вы можете выполнять итерации над objects_existing
, например:
hash_in_all_hashes = [obj.hash_in_all_hashes for obj in objects_existing] => [True, False, ...]
Ор:
hash_in_all_hashes_list = list(objects_existing.values_list('hash_in_all_hashes', flat=True)) => [True, False, ...]