如何在不保存的情况下持久修改查询集的切片

时间:2017-10-31 09:28:54

标签: python django python-3.x

我正在为搜索结果查询集中的对象转换(突出显示查询匹配)content属性。在查询集中枚举上的每个对象期间转换属性时,转换仍然存在,至少在查询集的生命周期内。出于显而易见的原因,我没有应用保存,因为我只希望转换在请求期间持续查询集的生命周期。

当我尝试将枚举优化为查询集的切片时,问题就出现了,然后转换不再(暂时)持续

  • 是否还可以为切片保留转换?
  • 为什么我的转换对于切片的处理方式与完整查询集的处理方式不同?

查询集的一部分仍然是一个查询集,尽管它没有等价 到原始查询集,即使它是整个查询集的一部分。

  • 使用Django 1.11.4和Python 3.6.3

这是一个展示一般问题的例子:

class Passage(models.Model):
    content = models.CharField(max_length=256)

Passage.objects.create(content='test 1')
Passage.objects.create(content='test 2')

In [1]: results = Passage.objects.filter(id__lte=2)
In [2]: for result in results:
   ...:     result.content = "hello world"
   ...:
In [3]: [result.content for result in results]
Out[3]: ['hello world', 'hello world']
In [4]: results = Passage.objects.filter(id__lte=2)
In [5]: for result in results[0:2]:
   ...:     result.content = "hello world"
   ...:
In [6]: [result.content for result in results]
Out[6]: ['test 1', 'test 2']

1 个答案:

答案 0 :(得分:2)

编辑查询集的切片不会影响原始查询集,因为切片是一个单独的查询集对象;这两个查询集被懒惰地评估,并且不共享内存中的模型对象。 results将为您提供一个queryset对象,results[0:2]将返回一个单独的queryset对象,当您迭代该对象时,另一个的结果将不会受到影响,因为它们是在您迭代时生成的(并缓存在queryset对象上,这就是你的第一个例子工作的原因)。

根据数据的大小,您可以通过使用枚举迭代来获得所需的效果:

for i, result in enumerate(results):
    if i < 2:
        result.content = 'hello world'