[Django]-Django objects change model field

11👍

>>> 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.

5👍

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
👤kender

2👍

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).

Leave a comment