Ticket #17813: first_latest_with_tests.patch

File first_latest_with_tests.patch, 4.2 KB (added by jimmysong, 3 years ago)

added tests, fixed the fact that the model manager didn't have a first() method.

  • django/db/models/manager.py

    diff --git a/django/db/models/manager.py b/django/db/models/manager.py
    index e1bbf6e..3e05f82 100644
    a b class Manager(object): 
    160160    def iterator(self, *args, **kwargs):
    161161        return self.get_query_set().iterator(*args, **kwargs)
    162162
     163    def first(self, *args, **kwargs):
     164        return self.get_query_set().first(*args, **kwargs)
     165
    163166    def latest(self, *args, **kwargs):
    164167        return self.get_query_set().latest(*args, **kwargs)
    165168
  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index 08fda78..c4b68ee 100644
    a b class QuerySet(object): 
    458458                    # Re-raise the IntegrityError with its original traceback.
    459459                    raise exc_info[1], None, exc_info[2]
    460460
    461     def latest(self, field_name=None):
     461    def _first_or_latest(self, field_name=None, direction="-"):
    462462        """
    463463        Returns the latest object, according to the model's 'get_latest_by'
    464464        option or optional given field_name.
    465465        """
    466         latest_by = field_name or self.model._meta.get_latest_by
    467         assert bool(latest_by), "latest() requires either a field_name parameter or 'get_latest_by' in the model"
     466        order_by = field_name or self.model._meta.get_latest_by
     467        assert bool(order_by), \
     468               "_first_or_latest() requires either a field_name parameter or 'get_latest_by' in the model"
    468469        assert self.query.can_filter(), \
    469470                "Cannot change a query once a slice has been taken."
    470471        obj = self._clone()
    471472        obj.query.set_limits(high=1)
    472473        obj.query.clear_ordering()
    473         obj.query.add_ordering('-%s' % latest_by)
     474        obj.query.add_ordering('%s%s' % (direction, order_by))     
    474475        return obj.get()
     476   
     477    def first(self, field_name=None):
     478        return self._first_or_latest(field_name=field_name, direction="")
     479   
     480    def latest(self, field_name=None):
     481        return self._first_or_latest(field_name=field_name, direction="-")
     482   
    475483
    476484    def in_bulk(self, id_list):
    477485        """
  • tests/modeltests/get_latest/tests.py

    diff --git a/tests/modeltests/get_latest/tests.py b/tests/modeltests/get_latest/tests.py
    index 948af60..684c426 100644
    a b from .models import Article, Person 
    88
    99
    1010class LatestTests(TestCase):
     11    def test_first(self):
     12        # Because no Articles exist yet, first() raises ArticleDoesNotExist.
     13        self.assertRaises(Article.DoesNotExist, Article.objects.first)
     14
     15        a1 = Article.objects.create(
     16            headline="Article 1", pub_date=datetime(2005, 7, 26),
     17            expire_date=datetime(2005, 9, 1)
     18        )
     19        a2 = Article.objects.create(
     20            headline="Article 2", pub_date=datetime(2005, 7, 27),
     21            expire_date=datetime(2005, 7, 28)
     22        )
     23        a3 = Article.objects.create(
     24            headline="Article 3", pub_date=datetime(2005, 7, 28),
     25            expire_date=datetime(2005, 8, 27)
     26        )
     27        a4 = Article.objects.create(
     28            headline="Article 4", pub_date=datetime(2005, 7, 28),
     29            expire_date=datetime(2005, 7, 30)
     30        )
     31
     32        # Get the first Article.
     33        self.assertEqual(Article.objects.first(), a1)
     34        # Get the first Article that matches certain filters.
     35        self.assertEqual(
     36            Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).first(),
     37            a2
     38        )
     39
     40        # Pass a custom field name to first() to change the field that's used
     41        # to determine the first object.
     42        self.assertEqual(Article.objects.first('expire_date'), a2)
     43        self.assertEqual(
     44            Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).first('expire_date'),
     45            a2,
     46        )
     47
     48        # Ensure that first() overrides any other ordering specified on the query. Refs #11283.
     49        self.assertEqual(Article.objects.order_by('id').first(), a1)
     50
    1151    def test_latest(self):
    1252        # Because no Articles exist yet, latest() raises ArticleDoesNotExist.
    1353        self.assertRaises(Article.DoesNotExist, Article.objects.latest)
Back to Top