如何复制查询集Django

Posted

技术标签:

【中文标题】如何复制查询集Django【英文标题】:How to copy queryset Django 【发布时间】:2016-12-28 00:43:15 【问题描述】:

我试图在 def save_related(self, request, form, *args, **kwargs) 方法中保存之前和之后访问 ManyToManyField 的查询集。 我想比较它们并获得添加到 ManyToManyField 中的新对象。

所以,我得到了旧的查询集:

def save_related(self, request, form, * args, * * kwargs):
    obj = form.instance
    queryset_before = obj.translations.all()
    print(queryset_before)
    super(WordAdmin, self).save_related(request, form, * args, * * kwargs) 
    print(queryset_before)

但是 print(queryset_before) 在调用 super().save_related 之后输出新的、更新的查询集。

所以:

    如何复制queryset,不影响保存? 或者有没有办法更正确地比较 ManyToManyField 的新旧值?

【问题讨论】:

【参考方案1】:

您可以获取保存前后的 ID 列表,然后比较这些列表:

def save_related(self, request, form, *args, **kwargs):
    obj = form.instance
    list_before = list(obj.translations.all().values_list('pk', flat=True))
    super(WordAdmin, self).save_related(request, form, *args, ** kwargs) 
    list_after = list(obj.translations.all().values_list('pk', flat=True))
    added_ids = [x for x in list_after if x not in list_before]
    removed_ids = [y for y in list_before if y not in list_after]

【讨论】:

【参考方案2】:

问题是打印查询集只会评估查询集的一部分,因此它不会填充查询集的内部缓存。

您需要在进行更改之前完全评估查询集,以便填充内部缓存。最简单的方法是使用bool() 函数:

def save_related(self, request, form, *args, **kwargs):
    obj = form.instance
    queryset_before = obj.translations.all()
    bool(queryset_before)
    print(queryset_before)
    super(WordAdmin, self).save_related(request, form, *args, **kwargs) 
    print(queryset_before)

现在两个打印语句应该给你相同的结果。

【讨论】:

以上是关于如何复制查询集Django的主要内容,如果未能解决你的问题,请参考以下文章

Django 可重用查询集

Django - 查询集不显示来自 db 的结果

如何合并两个查询集并在 django 中创建新的查询集

如何获取与传递给 Django 模板的查询集相关的查询集对象

如何链接 Django 查询集以保留单个顺序

如何在 Django 中查看表单和查询集?