Commit ea9a0857 authored by Selwin Ong's avatar Selwin Ong Committed by Anssi Kääriäinen
Browse files

Fixed #19326 -- Added first() and last() methods to QuerySet

parent d595b61a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -186,6 +186,12 @@ class Manager(six.with_metaclass(RenameManagerMethods)):
    def latest(self, *args, **kwargs):
        return self.get_queryset().latest(*args, **kwargs)

    def first(self):
        return self.get_queryset().first()

    def last(self):
        return self.get_queryset().last()

    def order_by(self, *args, **kwargs):
        return self.get_queryset().order_by(*args, **kwargs)

+20 −0
Original line number Diff line number Diff line
@@ -498,6 +498,26 @@ class QuerySet(object):
    def latest(self, field_name=None):
        return self._earliest_or_latest(field_name=field_name, direction="-")

    def first(self):
        """
        Returns the first object of a query, returns None if no match is found.
        """
        qs = self if self.ordered else self.order_by('pk')
        try:
            return qs[0]
        except IndexError:
            return None

    def last(self):
        """
        Returns the last object of a query, returns None if no match is found.
        """
        qs = self.reverse() if self.ordered else self.order_by('-pk')
        try:
            return qs[0]
        except IndexError:
            return None

    def in_bulk(self, id_list):
        """
        Returns a dictionary mapping each of the given IDs to the object with
+30 −0
Original line number Diff line number Diff line
@@ -1585,6 +1585,36 @@ earliest
Works otherwise like :meth:`~django.db.models.query.QuerySet.latest` except
the direction is changed.

first
~~~~~
.. method:: first()

.. versionadded:: 1.6

Returns the first object matched by the queryset, or ``None`` if there
is no matching object. If the ``QuerySet`` has no ordering defined, then the
queryset is automatically ordered by the primary key.

Example::

    p = Article.objects.order_by('title', 'pub_date').first()

Note that ``first()`` is a convenience method, the following code sample is
equivalent to the above example::

    try:
        p = Article.objects.order_by('title', 'pub_date')[0]
    except IndexError:
        p = None

last
~~~~
.. method:: last()

.. versionadded:: 1.6

Works like  :meth:`first()` except the ordering is reversed.

aggregate
~~~~~~~~~

+5 −0
Original line number Diff line number Diff line
@@ -253,6 +253,11 @@ Minor features
  allow users to specify the primary keys of objects they want to dump.
  This option can only be used with one model.

* Added ``QuerySet`` methods :meth:`~django.db.models.query.QuerySet.first`
  and :meth:`~django.db.models.query.QuerySet.last` which are convenience
  methods returning the first or last object matching the filters. Returns
  ``None`` if there are no objects matching.

Backwards incompatible changes in 1.6
=====================================

+31 −0
Original line number Diff line number Diff line
@@ -121,3 +121,34 @@ class EarliestOrLatestTests(TestCase):
        p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3))
        self.assertRaises(AssertionError, Person.objects.latest)
        self.assertEqual(Person.objects.latest("birthday"), p2)

    def test_first(self):
        p1 = Person.objects.create(name="Bob", birthday=datetime(1950, 1, 1))
        p2 = Person.objects.create(name="Alice", birthday=datetime(1961, 2, 3))
        self.assertEqual(
            Person.objects.first(), p1)
        self.assertEqual(
            Person.objects.order_by('name').first(), p2)
        self.assertEqual(
            Person.objects.filter(birthday__lte=datetime(1955, 1, 1)).first(),
            p1)
        self.assertIs(
            Person.objects.filter(birthday__lte=datetime(1940, 1, 1)).first(),
            None)

    def test_last(self):
        p1 = Person.objects.create(
            name="Alice", birthday=datetime(1950, 1, 1))
        p2 = Person.objects.create(
            name="Bob", birthday=datetime(1960, 2, 3))
        # Note: by default PK ordering.
        self.assertEqual(
            Person.objects.last(), p2)
        self.assertEqual(
            Person.objects.order_by('-name').last(), p1)
        self.assertEqual(
            Person.objects.filter(birthday__lte=datetime(1955, 1, 1)).last(),
            p1)
        self.assertIs(
            Person.objects.filter(birthday__lte=datetime(1940, 1, 1)).last(),
            None)