合并两个 Django 查询集并删除共享公共值的重复对象

Merge two Django query sets and deduplicate objects sharing a common value

我有一个使用分段库的 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 字段,它不是强制唯一的,而是在根页面和它的段子页面之间的值相同。如果 only_segments 中存在具有相同 guid 的对象,我如何在合并它们时比较两个查询集的对象并从 not_segments 中省略对象?

获得 queryset = Page 1, Page 2 (for user), Page 3, Page 4 (for user)

的预期结果

如果 not_segmentsonly_segments 是来自同一模型的记录,您可以将它们与 OR (|) operator 组合起来生成另一个查询集。结果将是独特的项目。

deduplicated_qs = not_segments | only_segments

如果它们是来自不同模型的记录,那么您可以通过跟踪已添加的 guid 来手动过滤掉重复值,以便不再重新添加它们。

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'}