2

我希望执行以下操作:

people = People.objects.filter(date=date)
person = people[0]
person['salary'] = 45000

最后一行导致错误:

object does not support item assignment

为了调试这样的东西,我总是发现从一些工作开始并逐行修改直到出现问题更容易。

我想修改要在模板中呈现的对象。如果我尝试:

person.salary = 45000

没有错误,但尝试

print person.salary

之后立即导致打印原始值。更新:

在我的代码中,我实际上是在做:

people[0].salary = 45000

这是行不通的。由于某些原因

person = people[0]
person.salary = 45000

行得通。我认为这两段代码会完全相同

4

3 回答 3

5

person是一个对象,你需要这样做:

person.salary = 45000
person.save()

您应该阅读如何使用模型

于 2013-05-21T05:39:20.200 回答
3

查看 ID,似乎当您将条目分配给变量时,您得到的是它的副本,而不是它的原始引用:

In [11]: people = People.objects.filter(salary=100)
In [12]: person = people[0]
In [13]: person.salary = 5000
In [14]: print person.salary
5000
In [15]: people[0].salary
Out[15]: 100
In [16]: id(people[0])
Out[16]: 35312400
In [17]: id(person)
Out[17]: 35313104

那么,让我们深入看看它发生了什么。您知道在 Django 中,查询集仅在您需要它们的结果时才被评估(惰性评估)。引用Django 文档

切片。如限制查询集中所述,可以使用 Python 的数组切片语法对查询集进行切片。对未计算的 QuerySet 进行切片通常会返回另一个未计算的 QuerySet,但如果您使用切片语法的“step”参数,Django 将执行数据库查询,并返回一个列表。对已评估(部分或全部)的 QuerySet 进行切片也会返回一个列表。

特别是查看'django.db.models.query' 源代码

    def __getitem__(self, k):
    """
    Retrieves an item or slice from the set of results.
    """
    # some stuff here ...

    if isinstance(k, slice):
        qs = self._clone()
        if k.start is not None:
            start = int(k.start)
        else:
            start = None
        if k.stop is not None:
            stop = int(k.stop)
        else:
            stop = None
        qs.query.set_limits(start, stop)
        return k.step and list(qs)[::k.step] or qs

    qs = self._clone()
    qs.query.set_limits(k, k + 1)
    return list(qs)[0]

您可以看到,当您使用slicing时,您正在调用该__getitem__方法。然后该self._clone方法将为您提供同一 QuerySet 的不同实例。这就是你得到不同结果的原因。

于 2013-05-21T06:43:55.103 回答
0

Django 模型提供的对象关系映射通过提供面向对象的接口来检索和操作数据,隐藏了您正在与 DB 交互的事实。

不幸的是,ORM 抽象并不完美,ORM 语义与直觉不匹配的情况有很多种。在这些情况下,您需要调查底层 SQL 层发生的情况,以找出问题的原因。

您的问题源于以下事实:

people = People.objects.filter(date=date)

不执行任何 SQL 查询。

people[0]

执行SELECT a, b, c, .. FROM T WHERE filter,如果您通过调用修改生成的对象:

people[0].salary = 45000

修改不会保存到数据库中,因为save()没有调用该方法。下一次调用people[0]再次执行 SQL 查询,该查询不返回未保存的修改。

当您遇到这样的问题时,Django Debug Toolbar可以极大地帮助识别哪些语句执行哪些 SQL 查询。

于 2013-05-21T07:54:32.250 回答