0

我知道 django querysey 是一个生成器,而不是一个列表。

my_items = Item.objects.filter(id = 1)
my_items[0].name = 'joe'
my_items[0].save()

在示例中 my_items[0] 是对象的副本,因此保存不会修改对象。
虽然这会起作用(不会创建副本)

my_items = Item.objects.filter(id = 1)
my_item = my_items[0]
my_item.name = 'joe'
my_item.save()

它在 django 文档(或其他任何地方)的什么地方解释了这种行为?为什么他们选择返回对象的副本而不是对象本身?

4

2 回答 2

4

它记录在有关查询集和缓存的部分中。它不仅仅是现有对象的副本。每次执行此操作时,Django 都会对数据库进行单独的查询,并根据响应创建一个新对象。这是文档提供的示例:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again

但是,如果您的查询集已经被评估,使用索引运算符获取对象将不会命中数据库,并且您每次都会获得相同的对象(如文档中所示)。

更新:我被要求进一步澄清,所以这里是:

您认为您正在获取对象的副本,但严格来说并非如此。您将获得两个不同的 Python 对象,它们是独立创建的,但基于相同的数据库条目。那是因为每次您使用索引运算符时,都会查询数据库并创建一个新对象(前提是之前未评估该查询)。

在您的情况下,您两次使用运算符,两次都访问数据库。第一次在第二行:my_items[0].name = 'joe'; 第三行中的第二次:my_items[0].save(). 每次你my_items[0]都在使用操作符,查询数据库并创建一个新对象。因此,您保存的对象与您修改的对象不同。

于 2013-10-04T16:32:49.233 回答
0

您在第二行写“my_itMes”这一事实重要吗?

Item.objects.filter(pk = 1).update(name = 'Joe')

或者

myitem = Item.objects.get(id=1)
myitem.name = 'joe'
myitem.save()

https://docs.djangoproject.com/en/1.5/ref/models/instances/#updating-attributes-based-on-existing-fields

以及您要求的文件:

https://docs.djangoproject.com/en/1.5/topics/db/queries/#filtered-querysets-are-unique

每次优化 QuerySet 时,都会得到一个全新的 QuerySet,它绝不会绑定到以前的 QuerySet。每个细化创建一个单独且不同的 QuerySet,可以存储、使用和重用。

于 2013-10-04T16:27:48.283 回答