Slicing [-1] on objects.all()

1 view
Skip to first unread message

Jay Parlar

unread,
May 25, 2006, 10:38:16 AM5/25/06
to django...@googlegroups.com
I'm seeing some strange slicing behaviour (using sqlite3 and the dev server).

All I want to do is grab the last element in the table, so I'm trying this:

Foo.objects.all()[-1]

When I do that in a shell (via manage.py shell) it works fine, and
respects my 'ordering' Meta. However, when my application is actually
running, that same line will ALWAYS return the first row in the table,
not the last one.

Am I missing something here?

Jay P.

Ian Maurer

unread,
May 25, 2006, 11:28:11 AM5/25/06
to django...@googlegroups.com
Django's QuerySet handles slicing through the LIMIT and OFFSET clauses
of the database. Since the clauses cannot handle python's "negative
indexing" scheme, you have 2 choices:

1. Do the actual evaluation, by converting to a list and then doing your slice:

list(Foo.objects.all())[-1]

2. Use an order_by method to set the reverse order and then get the
first item, use a minus sign to denote DESC order:

Foo.objects.order_by("-column")[0]

The second option is FAR superior. The first solution is, IMO, totally
unacceptable since it retrieves all of the records just to access one
row.

For more information about the amazing Django QuerySets, check out this link:

http://www.djangoproject.com/documentation/db_api/

This section discusses slicing specifically:

http://www.djangoproject.com/documentation/db_api/#limiting-querysets

Hope that helps,
ian

Jay Parlar

unread,
May 25, 2006, 11:37:37 AM5/25/06
to django...@googlegroups.com
On 5/25/06, Ian Maurer <ima...@gmail.com> wrote:
>
> Django's QuerySet handles slicing through the LIMIT and OFFSET clauses
> of the database. Since the clauses cannot handle python's "negative
> indexing" scheme, you have 2 choices:
>
> 1. Do the actual evaluation, by converting to a list and then doing your slice:
>
> list(Foo.objects.all())[-1]
>
> 2. Use an order_by method to set the reverse order and then get the
> first item, use a minus sign to denote DESC order:
>
> Foo.objects.order_by("-column")[0]
>
> The second option is FAR superior. The first solution is, IMO, totally
> unacceptable since it retrieves all of the records just to access one
> row.
>
> For more information about the amazing Django QuerySets, check out this link:
>
> http://www.djangoproject.com/documentation/db_api/
>
> This section discusses slicing specifically:
>
> http://www.djangoproject.com/documentation/db_api/#limiting-querysets
>

Perfect, the 'order_by' worked beautifully!

Maybe a note should go into the db_api docs about -1 not working? I
did look at those docs before sending my original message, and didn't
see anything about that.

Jay P.

Jan Claeys

unread,
May 25, 2006, 10:31:28 PM5/25/06
to django...@googlegroups.com
Op do, 25-05-2006 te 11:28 -0400, schreef Ian Maurer:

> Django's QuerySet handles slicing through the LIMIT and OFFSET clauses
> of the database. Since the clauses cannot handle python's "negative
> indexing" scheme, you have 2 choices:
[...]

> 2. Use an order_by method to set the reverse order and then get the
> first item, use a minus sign to denote DESC order:
>
> Foo.objects.order_by("-column")[0]
>
> The second option is FAR superior. The first solution is, IMO, totally
> unacceptable since it retrieves all of the records just to access one
> row.

Quick thought: can't the QuerySet do that itself then?


--
Jan Claeys

Luke Plant

unread,
May 26, 2006, 9:37:38 AM5/26/06
to Django users

Jay Parlar wrote:

> Maybe a note should go into the db_api docs about -1 not working? I
> did look at those docs before sending my original message, and didn't
> see anything about that.

I think it should throw an exception saying that negative indices are
not supported (and even include a hint about reversing the ordering).
I'll get that fixed that soon, thanks.

Luke

Luke Plant

unread,
May 26, 2006, 2:17:06 PM5/26/06
to django...@googlegroups.com
On Friday 26 May 2006 03:31, Jan Claeys wrote:

> > 2. Use an order_by method to set the reverse order and then get the
> > first item, use a minus sign to denote DESC order:
> >
> > Foo.objects.order_by("-column")[0]
> >
> > The second option is FAR superior. The first solution is, IMO,
> > totally unacceptable since it retrieves all of the records just to
> > access one row.
>
> Quick thought: can't the QuerySet do that itself then?

No, inverting the ordering does not, strictly speaking, reverse the
result set, since 2 or more items can have the same sort order, in
which case their relative ordering (in the list returned by the DB) is
undefined. Foo.objects.order_by("column")[0] is not necessarily the
same as list(Foo.objects.order_by("-column"))[-1], so it would be
incorrect for a QuerySet to assume that.

Luke

--
The early bird gets the worm, but the second mouse gets the cheese.
--Steven Wright

Luke Plant || L.Plant.98 (at) cantab.net || http://lukeplant.me.uk/

Reply all
Reply to author
Forward
0 new messages