Слияние двух наборов запросов Django и дедупликация объектов, имеющих общее значение
У меня есть проект Django, использующий библиотеку сегментации, и мне нужно объединить два набора запросов и дедуплицировать полученный набор запросов, что заставляет меня ломать голову над тем, как это сделать.
not_segments = Page.objects.all().no_segments()
(перефразировано) дает мне страницы с исключенными страницами сегмента.
only_segments = Segment.objects.get_queryset().for_user(user=user)
(перефразировано) дает мне сегментированные объекты страниц из одной модели, но, конечно, есть перекрытия.
not_segments = Page 1, Page 2, Page 3, Page 4
only_segments = Page 2 (for user), Page 4 (for user)
Допустим, в модели есть поле guid, которое не является уникальным, а скорее идентичным по значению между корневой страницей и дочерней страницей ее сегмента. Как мне сравнить объекты двух наборов запросов при их объединении и опустить объекты из not_segments
, если объект с таким же guid существует в only_segments
?
Для получения желаемого результата queryset = Page 1, Page 2 (for user), Page 3, Page 4 (for user)
Если not_segments
и only_segments
являются записями из одной и той же модели, вы можете просто объединить их с помощью оператора OR (|) , создав другой кверисет. В результате будут получены уникальные элементы.
deduplicated_qs = not_segments | only_segments
Если это записи из разных моделей, то можно вручную отфильтровать дублирующиеся значения, отслеживая уже добавленные направляющие, чтобы не добавлять их снова.
import itertools
# To simplify the example, this is just a raw Python-class. In reality, this would be the Django-model-class.
class Page:
def __init__(self, guid, value):
self.guid = guid
self.value = value
class Segment:
def __init__(self, guid, other_value):
self.guid = guid
self.other_value = other_value
only_segments = [
Page(2, 'A'),
Page(4, 'B'),
]
not_segments = [
Segment(1, 'C'),
Segment(2, 'D'),
Segment(3, 'E'),
Segment(4, 'F'),
]
added_guids = set()
deduplicated_pages = list()
for page_or_segment in itertools.chain(only_segments, not_segments):
if page_or_segment.guid in added_guids:
continue
added_guids.add(page_or_segment.guid)
deduplicated_pages.append(page_or_segment)
for page in deduplicated_pages:
print(type(page), page.__dict__)
Выход
<class '__main__.Page'> {'guid': 2, 'value': 'A'}
<class '__main__.Page'> {'guid': 4, 'value': 'B'}
<class '__main__.Segment'> {'guid': 1, 'other_value': 'C'}
<class '__main__.Segment'> {'guid': 3, 'other_value': 'E'}