Слияние двух наборов запросов 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'}
Вернуться на верх