Reputation: 87077
This doesn't work:
>>> pa = Person.objects.all()
>>> pa[2].nickname
u'arst'
>>> pa[2].nickname = 'something else'
>>> pa[2].save()
>>> pa[2].nickname
u'arst'
But it works if you take
p = Person.objects.get(pk=2)
and change the nick.
Why so.
Upvotes: 3
Views: 5905
Reputation: 126541
Person.objects.all()
returns a QuerySet
, which is lazy (doesn't perform a DB query until data is requested from it). Slicing a QuerySet
(pa[2]) performs a database query to get a single row from the database (using LIMIT and OFFSET in SQL). Slicing the same QuerySet
again doesn't do the DB query again (results are cached) but it does return a new instance of the model. Each time you access pa[2] you are getting a new Person instance (albeit with all the same data in it).
Upvotes: 2
Reputation: 61021
>>> 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'>
DB queried to give you a Person object
>>> pa[2]
DB queried again to give you yet another Person object.
>>> pa[2].first_name = "Blah"
Let's call this instance PersonObject1 that resides in memory. So it's equivalent to something like this:
>>> PersonObject1.first_name = "Blah"
Now let's do this:
>>> pa[2].save()
The pa[2] again queries a db an returns Another instance of person object, say PersonObject2 for example. Which will be unchanged! So it's equvivalent to calling something like:
PersonObject2.save()
But this has nothing to do with PersonObject1.
Upvotes: 11
Reputation: 87131
If you assigned your pa[2]
to a variable, like you do with Person.objects.get(pk=2)
you'd have it right:
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'
This has nothing to do with the method you pull the objects from database.
And, btw, django numbers PrimaryKeys starting from 1, not 0, so
Person.objects.all()[2] == Person.objects.get(pk=2)
False
Person.objects.all()[2] == Person.objects.get(pk=3)
True
Upvotes: 5