2009-05-26 2 views

ответ

10
>>> 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 запрашивается, чтобы дать вам объект Person

>>> pa[2] 

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

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

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

>>> PersonObject1.first_name = "Blah" 

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

>>> pa[2].save() 

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

PersonObject2.save() 

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

+0

Очень хорошо объяснено! Благодаря! –

4

Если вы назначили 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 
+0

+1 Отличный ответ, очень информативный (особенно последняя часть ...) –

+3

Было бы полезно упомянуть, что all() - это QuerySet, а не фактический список. http://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-all-objects –

+0

Спасибо за указание – kender

2

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

Смежные вопросы