On 10 November 2010 22:10, Shawn Milochik <sh...@milochik.com> wrote:
> 2010/11/10 Łukasz Rekucki <lreku...@gmail.com>:
>> On 10 November 2010 21:55, Shawn Milochik <sh...@milochik.com> wrote:
>>> The queryset returns zero or more instances of your model. So if
>>> there's only one result, you can just get the first item in the
>>> queryset by its index.
>>>
>>> For example:
>>>
>>> some_queryset = YourModel.objects.filter(**kwargs)
>>>
>>> if some_queryset.count() == 1:
>>>    x = some_queryset[0]
>>>    #x is now an instance of your model.
>>> else:
>>>    raise ValueError("%d results -- expected one!" % (some_queryset.count(),)
>>
>> This is a very bad way of checking queryset length, because count()
>> actually creates a new QuerySet that gets executed (again!). Instead
>> use len() that will first check against queryset's internal cache.
>
> I agree that your way is better, but I disagree about duplicate
> execution -- doing a count() will simply run a SQL query that does a
> COUNT. It's not doing anything "again" because the original queryset
> hasn't actually been executed (lazy) until its contents are actually
> used (as in the variable assignment), and the COUNT statement is
> lightweight.

Yes, the original query is lazy. But the common case here is probably
that element exists, so most of the time you will be doing:

some_queryset.count() # ~= SELECT COUNT(*) FROM ...
some_queryset[0] # ~= SELECT mymodel.* FROM ... LIMIT 1

How those queries are performed of course depends on the params you
pass to filter(), but the COUNT() is not as light-weight as you think.
Assuming the simplest case of filtering by primary key, It's actually
pretty slow and requires to go through the whole index (or even a full
table scan), while a LIMIT 1 query usualy just fetches the first
element in the db index. This is why Django 1.2 has .exists() which
uses LIMIT 1.

-- 
Łukasz Rekucki

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

Reply via email to