Ticket #17813: t17813.3.diff

File t17813.3.diff, 14.7 KB (added by Adrien Lemaire, 13 years ago)

get_earliest_by attr related code reverted

  • django/db/models/manager.py

    diff --git a/django/db/models/manager.py b/django/db/models/manager.py
    index e1bbf6e..cc00fed 100644
    a b class Manager(object):  
    160160    def iterator(self, *args, **kwargs):
    161161        return self.get_query_set().iterator(*args, **kwargs)
    162162
     163    def earliest(self, *args, **kwargs):
     164        return self.get_query_set().earliest(*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 44acadf..4fa38df 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 _earliest_or_latest(self, field_name=None, direction="-"):
    462462        """
    463         Returns the latest object, according to the model's 'get_latest_by'
    464         option or optional given field_name.
     463        Returns the latest object, according to the model's
     464        'get_latest_by' 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 getattr(self.model._meta, 'get_latest_by')
     467        assert bool(order_by), "_earliest_or_latest() requires either a "\
     468            "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()
    475476
     477    def earliest(self, field_name=None):
     478        return self._earliest_or_latest(field_name=field_name, direction="")
     479
     480    def latest(self, field_name=None):
     481        return self._earliest_or_latest(field_name=field_name, direction="-")
     482
    476483    def in_bulk(self, id_list):
    477484        """
    478485        Returns a dictionary mapping each of the given IDs to the object with
  • docs/ref/models/options.txt

    diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
    index 6ca3d3b..3e77b8b 100644
    a b Django quotes column and table names behind the scenes.  
    7878    setting, if set. If the backend doesn't support tablespaces, this option is
    7979    ignored.
    8080
     81
    8182``get_latest_by``
    8283-----------------
    8384
  • docs/ref/models/querysets.txt

    diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
    index e25bea0..34e3fac 100644
    a b This example returns the latest ``Entry`` in the table, according to the  
    14661466
    14671467If your model's :ref:`Meta <meta-options>` specifies
    14681468:attr:`~django.db.models.Options.get_latest_by`, you can leave off the
    1469 ``field_name`` argument to ``latest()``. Django will use the field specified
    1470 in :attr:`~django.db.models.Options.get_latest_by` by default.
     1469``field_name`` argument to ``earliest()`` or ``latest()``. Django will use the
     1470field specified in :attr:`~django.db.models.Options.get_latest_by` by default.
    14711471
    1472 Like :meth:`get()`, ``latest()`` raises
    1473 :exc:`~django.core.exceptions.DoesNotExist` if there is no object with the given
    1474 parameters.
     1472Like :meth:`get()`, ``earliest()`` and ``latest()`` raise
     1473:exc:`~django.core.exceptions.DoesNotExist` if there is no object with the
     1474given parameters.
    14751475
    1476 Note ``latest()`` exists purely for convenience and readability.
     1476Note that ``earliest()`` and ``latest()`` exist purely for convenience and
     1477readability.
    14771478
    14781479aggregate
    14791480~~~~~~~~~
  • docs/topics/db/models.txt

    diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt
    index 9a4010d..14f216d 100644
    a b right).  
    991991
    992992So a child model does not have access to its parent's :ref:`Meta
    993993<meta-options>` class. However, there are a few limited cases where the child
    994 inherits behavior from the parent: if the child does not specify an
    995 :attr:`~django.db.models.Options.ordering` attribute or a
    996 :attr:`~django.db.models.Options.get_latest_by` attribute, it will inherit
    997 these from its parent.
     994inherits behavior from the parent: if the child does not specify an attribute
     995:attr:`~django.db.models.Options.ordering` or
     996:attr:`~django.db.models.Options.get_latest_by`,
     997, it will inherit these from its parent.
    998998
    999999If the parent has an ordering and you don't want the child to have any natural
    10001000ordering, you can explicitly disable it::
  • new file tests/modeltests/get_earliest_or_latest/models.py

    diff --git a/tests/modeltests/get_earliest_or_latest/__init__.py b/tests/modeltests/get_earliest_or_latest/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/modeltests/get_earliest_or_latest/models.py b/tests/modeltests/get_earliest_or_latest/models.py
    new file mode 100644
    index 0000000..2453eaa
    - +  
     1"""
     28. get_latest_by
     3
     4Models can have a ``get_latest_by`` attribute, which should be set to the name
     5of a ``DateField`` or ``DateTimeField``. If ``get_latest_by`` exists, the
     6model's manager will get a ``latest()`` method, which will return the latest
     7object in the database according to that field. "Latest" means "having the date
     8farthest into the future."
     9"""
     10
     11from django.db import models
     12
     13
     14class Article(models.Model):
     15    headline = models.CharField(max_length=100)
     16    pub_date = models.DateField()
     17    expire_date = models.DateField()
     18    class Meta:
     19        get_latest_by = 'pub_date'
     20
     21    def __unicode__(self):
     22        return self.headline
     23
     24
     25class Person(models.Model):
     26    name = models.CharField(max_length=30)
     27    birthday = models.DateField()
     28
     29    # Note that this model doesn't have "get_latest_by" set.
     30
     31    def __unicode__(self):
     32        return self.name
  • new file tests/modeltests/get_earliest_or_latest/tests.py

    diff --git a/tests/modeltests/get_earliest_or_latest/tests.py b/tests/modeltests/get_earliest_or_latest/tests.py
    new file mode 100644
    index 0000000..a78af2a
    - +  
     1from __future__ import absolute_import
     2
     3from datetime import datetime
     4
     5from django.test import TestCase
     6
     7from .models import Article, Person
     8
     9
     10class EarliestOrLatestTests(TestCase):
     11    """Tests for the earliest() and latest() objects methods"""
     12
     13    def test_earliest(self):
     14        # Because no Articles exist yet, earliest() raises ArticleDoesNotExist.
     15        self.assertRaises(Article.DoesNotExist, Article.objects.earliest)
     16
     17        a1 = Article.objects.create(
     18            headline="Article 1", pub_date=datetime(2005, 7, 26),
     19            expire_date=datetime(2005, 9, 1)
     20        )
     21        a2 = Article.objects.create(
     22            headline="Article 2", pub_date=datetime(2005, 7, 27),
     23            expire_date=datetime(2005, 7, 28)
     24        )
     25        a3 = Article.objects.create(
     26            headline="Article 3", pub_date=datetime(2005, 7, 28),
     27            expire_date=datetime(2005, 8, 27)
     28        )
     29        a4 = Article.objects.create(
     30            headline="Article 4", pub_date=datetime(2005, 7, 28),
     31            expire_date=datetime(2005, 7, 30)
     32        )
     33
     34        # Get the earliest Article.
     35        self.assertEqual(Article.objects.earliest(), a1)
     36        # Get the earliest Article that matches certain filters.
     37        self.assertEqual(
     38            Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).earliest(),
     39            a2
     40        )
     41
     42        # Pass a custom field name to earliest() to change the field that's used
     43        # to determine the earliest object.
     44        self.assertEqual(Article.objects.earliest('expire_date'), a2)
     45        self.assertEqual(Article.objects.filter(
     46            pub_date__gt=datetime(2005, 7, 26)).earliest('expire_date'), a2)
     47
     48        # Ensure that earliest() overrides any other ordering specified on the
     49        # query. Refs #11283.
     50        self.assertEqual(Article.objects.order_by('id').earliest(), a1)
     51
     52        # Ensure that error is raised if the user forgot to add a get_earliest_by
     53        # in the Model.Meta
     54        Article.objects.model._meta.get_earliest_by = None
     55        self.assertRaisesMessage(
     56            AssertionError,
     57            "_earliest_or_latest() requires either a field_name parameter or "\
     58                "'get_earliest_by' in the model",
     59            lambda: Article.objects.earliest(),
     60        )
     61
     62
     63    def test_latest(self):
     64        # Because no Articles exist yet, latest() raises ArticleDoesNotExist.
     65        self.assertRaises(Article.DoesNotExist, Article.objects.latest)
     66
     67        a1 = Article.objects.create(
     68            headline="Article 1", pub_date=datetime(2005, 7, 26),
     69            expire_date=datetime(2005, 9, 1)
     70        )
     71        a2 = Article.objects.create(
     72            headline="Article 2", pub_date=datetime(2005, 7, 27),
     73            expire_date=datetime(2005, 7, 28)
     74        )
     75        a3 = Article.objects.create(
     76            headline="Article 3", pub_date=datetime(2005, 7, 27),
     77            expire_date=datetime(2005, 8, 27)
     78        )
     79        a4 = Article.objects.create(
     80            headline="Article 4", pub_date=datetime(2005, 7, 28),
     81            expire_date=datetime(2005, 7, 30)
     82        )
     83
     84        # Get the latest Article.
     85        self.assertEqual(Article.objects.latest(), a4)
     86        # Get the latest Article that matches certain filters.
     87        self.assertEqual(
     88            Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest(),
     89            a1
     90        )
     91
     92        # Pass a custom field name to latest() to change the field that's used
     93        # to determine the latest object.
     94        self.assertEqual(Article.objects.latest('expire_date'), a1)
     95        self.assertEqual(
     96            Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date'),
     97            a3,
     98        )
     99
     100        # Ensure that latest() overrides any other ordering specified on the query. Refs #11283.
     101        self.assertEqual(Article.objects.order_by('id').latest(), a4)
     102
     103        # Ensure that error is raised if the user forgot to add a get_latest_by
     104        # in the Model.Meta
     105        Article.objects.model._meta.get_latest_by = None
     106        self.assertRaisesMessage(
     107            AssertionError,
     108            "_earliest_or_latest() requires either a field_name parameter or "\
     109                "'get_latest_by' in the model",
     110            lambda: Article.objects.latest(),
     111        )
     112
     113
     114    def test_latest_manual(self):
     115        # You can still use latest() with a model that doesn't have
     116        # "get_latest_by" set -- just pass in the field name manually.
     117        p1 = Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1))
     118        p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3))
     119        self.assertRaises(AssertionError, Person.objects.latest)
     120
     121        self.assertEqual(Person.objects.latest("birthday"), p2)
  • deleted file tests/modeltests/get_latest/models.py

    diff --git a/tests/modeltests/get_latest/__init__.py b/tests/modeltests/get_latest/__init__.py
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/tests/modeltests/get_latest/models.py b/tests/modeltests/get_latest/models.py
    deleted file mode 100644
    index d8a690f..0000000
    + -  
    1 """
    2 8. get_latest_by
    3 
    4 Models can have a ``get_latest_by`` attribute, which should be set to the name
    5 of a ``DateField`` or ``DateTimeField``. If ``get_latest_by`` exists, the
    6 model's manager will get a ``latest()`` method, which will return the latest
    7 object in the database according to that field. "Latest" means "having the date
    8 farthest into the future."
    9 """
    10 
    11 from django.db import models
    12 
    13 
    14 class Article(models.Model):
    15     headline = models.CharField(max_length=100)
    16     pub_date = models.DateField()
    17     expire_date = models.DateField()
    18     class Meta:
    19         get_latest_by = 'pub_date'
    20 
    21     def __unicode__(self):
    22         return self.headline
    23 
    24 class Person(models.Model):
    25     name = models.CharField(max_length=30)
    26     birthday = models.DateField()
    27 
    28     # Note that this model doesn't have "get_latest_by" set.
    29 
    30     def __unicode__(self):
    31         return self.name
  • deleted file tests/modeltests/get_latest/tests.py

    diff --git a/tests/modeltests/get_latest/tests.py b/tests/modeltests/get_latest/tests.py
    deleted file mode 100644
    index 948af60..0000000
    + -  
    1 from __future__ import absolute_import
    2 
    3 from datetime import datetime
    4 
    5 from django.test import TestCase
    6 
    7 from .models import Article, Person
    8 
    9 
    10 class LatestTests(TestCase):
    11     def test_latest(self):
    12         # Because no Articles exist yet, latest() raises ArticleDoesNotExist.
    13         self.assertRaises(Article.DoesNotExist, Article.objects.latest)
    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, 27),
    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 latest Article.
    33         self.assertEqual(Article.objects.latest(), a4)
    34         # Get the latest Article that matches certain filters.
    35         self.assertEqual(
    36             Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest(),
    37             a1
    38         )
    39 
    40         # Pass a custom field name to latest() to change the field that's used
    41         # to determine the latest object.
    42         self.assertEqual(Article.objects.latest('expire_date'), a1)
    43         self.assertEqual(
    44             Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date'),
    45             a3,
    46         )
    47 
    48         # Ensure that latest() overrides any other ordering specified on the query. Refs #11283.
    49         self.assertEqual(Article.objects.order_by('id').latest(), a4)
    50 
    51     def test_latest_manual(self):
    52         # You can still use latest() with a model that doesn't have
    53         # "get_latest_by" set -- just pass in the field name manually.
    54         p1 = Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1))
    55         p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3))
    56         self.assertRaises(AssertionError, Person.objects.latest)
    57 
    58         self.assertEqual(Person.objects.latest("birthday"), p2)
Back to Top