Объекты Django меняют поле модели - PullRequest
2 голосов
/ 26 мая 2009

Это не работает:

>>> pa = Person.objects.all()
>>> pa[2].nickname
u'arst'
>>> pa[2].nickname = 'something else'
>>> pa[2].save()
>>> pa[2].nickname  
u'arst'

Но это работает, если вы берете

   p = Person.objects.get(pk=2)

и смени ник.

Почему так.

Ответы [ 3 ]

10 голосов
/ 26 мая 2009
>>> type(Person.objects.all())
<class 'django.db.models.query.QuerySet'>

>>> pa = Person.objects.all() # Not evaluated yet - lazy
>>> type(pa)
<class 'django.db.models.query.QuerySet'>

БД запрашивает у вас объект Person

>>> pa[2]

БД снова запросил, чтобы дать вам еще один объект Person.

>>> pa[2].first_name = "Blah" 

Давайте назовем этот экземпляр PersonObject1, который находится в памяти. Так что это эквивалентно примерно так:

>>> PersonObject1.first_name = "Blah"

Теперь давайте сделаем это:

>>> pa[2].save() 

PA [2] снова запрашивает DB и возвращает другой экземпляр объекта person, например, PersonObject2 Который будет неизменным! Так что эквивалентно называть что-то вроде:

PersonObject2.save()

Но это не имеет ничего общего с PersonObject1.

4 голосов
/ 26 мая 2009

Если бы вы присвоили pa[2] переменной, как вы делаете с Person.objects.get(pk=2), вы бы получили право:

pa = Person.objects.all()
print pa[2].nickname
'Jonny'
pa[2].nickname = 'Billy'
print pa[2].nickname
'Jonny'

# when you assign it to some variable, your operations 
# change this particular object, not something that is queried out each time
p1 = pa[2]
print p1.nickname 
'Jonny'
p1.nickname = 'Billy'
print p1.nickname 
'Billy'

Это не имеет ничего общего с методом извлечения объектов из базы данных.

И, между прочим, числа Джанго PrimaryKeys начинаются с 1, а не с 0, поэтому

Person.objects.all()[2] == Person.objects.get(pk=2)
False
Person.objects.all()[2] == Person.objects.get(pk=3)
True
2 голосов
/ 26 мая 2009

Person.objects.all() возвращает QuerySet, что является ленивым (не выполняет запрос к БД, пока от него не будут запрошены данные). Нарезка QuerySet (pa [2]) выполняет запрос к базе данных, чтобы получить одну строку из базы данных (используя LIMIT и OFFSET в SQL). Повторная нарезка того же QuerySet не делает запрос к БД снова (результаты кэшируются), но он возвращает новый экземпляр модели. Каждый раз, когда вы обращаетесь к pa [2], вы получаете новый экземпляр Person (хотя со всеми теми же данными в нем).

...