Adrian Holovaty wrote:
> On Dec 2, 2007 11:50 PM, James Bennett <[EMAIL PROTECTED]> wrote:
>> I guess I'm curious as to what's difficult or error-prone about it;
>> I've never run into a problem where slicing was the cuplrit, and it
>> feels like a more intuitive and Pythonic syntax than the "limit" and
>> "offset" arguments we used to have in the pre-magic-removal days.
> 
> Here's a specific problem that's bitten me a number of times. I want
> to get a list of model objects and do something special with the first
> one. I want to pass both the full list and the first one to the
> template.
> 
>     objects = MyModel.objects.filter(site=1)
>     first_one = objects[0]
>     do_something_special(first_one)
>     return render_to_response('t.html', {'objects': objects, 'first':
> first_one})
> 
> Although this works, it performs two database queries -- one to
> retrieve all of the objects, and one to retrieve the first one (with a
> "LIMIT" clause). That's unacceptable.

But what would the situation be with a new limit() method...

objects = MyModel.objects.filter(site=1)
first_one = objects.limit(1)
do_something_special(first_one)
return render_to_response('t.html', {'objects': objects, 'first': first_one})

If limit() returns a new QuerySet, you're still going to have two queries.

Now, maybe we could introduce some mechanics into QuerySet so that your new
QuerySet returned by limit() would keep a reference to the original QuerySet
to use for slicing it's cached results (evaluating it if it hasn't already
been evaluated).  Of course, something like this would also fix the two
queries with slicing :)


On a similar note, we have two-query situations happening with count() and
values() too...

objects = MyModel.objects.filter(site=1)
count = objects.count()

objects = MyModel.objects.filter(site=1)
skinny_objects = objects.values('field1')

both of which could use an optimization if their original QuerySet has already
been evaluated.

> The (unintuitive) way to fix the problem is to wrap the first line in list() 
> --
> 
>     objects = list(MyModel.objects.filter(site=1))

Another option might be to make slicing return a list and not a QuerySet,
which is already happening if you use a step with your slice.

> The counter argument here is, "Well, that's exactly what you have to
> do with any iteratable." And my counter argument to that is, "Yeah,
> but normal iterables raise TypeError when you try to slice them."

And I say QuerySets are more like lazy-evaluated lists.  lists are iterable
and can be sliced.

> The confusion here stems from the fact that a QuerySet *sometimes*
> behaves like a list, but not always. After the QuerySet has been
> evaluated, then the slicing syntax simply selects items from the list,
> but before the QuerySet has been evaluated, the slicing syntax acts as
> a LIMIT/OFFSET. Different things happen depending on the context --
> and that's what I find confusing.

I don't see how this fact would lead to confusion as this is only how things
work behind the scenes.  To the developer using a QuerySet, it behaves like a
list no matter if the QuerySet has been evaluated or not.  I do agree however,
that we be efficient as possible on the backend.

> My problem with the slicing syntax is that it's the *only* part of the
> QuerySet API that uses Python syntax hacking -- as in, "the plus sign
> now does something different," or "the slice operator now does
> something different." Everything else in the API uses normal Python
> methods. It's this inconsistency that bothers me.
> 
> I'm still +1 on fixing this wart, but it won't be the end of the world
> if nobody agrees with me. I just want folks to understand my
> reasoning.

I wouldn't be against adding limit() and offset() to _complement_ the existing
slicing capability.  So call me +0 for adding limit() and offset() and -1 for
removing slicing support.

Gary

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to