Refs #11557 -- Removed the field_name keyword argument to QuerySet.earliest() and latest().

Per deprecation timeline.
This commit is contained in:
Tim Graham 2018-12-27 20:18:45 -05:00
parent da5eb3d56c
commit 1fecde6be9
3 changed files with 9 additions and 37 deletions

View File

@ -25,7 +25,6 @@ from django.db.models.query_utils import FilteredRelation, InvalidQuery, Q
from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE
from django.db.utils import NotSupportedError from django.db.utils import NotSupportedError
from django.utils import timezone from django.utils import timezone
from django.utils.deprecation import RemovedInDjango30Warning
from django.utils.functional import cached_property, partition from django.utils.functional import cached_property, partition
from django.utils.version import get_version from django.utils.version import get_version
@ -607,22 +606,12 @@ class QuerySet:
)) ))
return params return params
def _earliest(self, *fields, field_name=None): def _earliest(self, *fields):
""" """
Return the earliest object according to fields (if given) or by the Return the earliest object according to fields (if given) or by the
model's Meta.get_latest_by. model's Meta.get_latest_by.
""" """
if fields and field_name is not None: if fields:
raise ValueError('Cannot use both positional arguments and the field_name keyword argument.')
if field_name is not None:
warnings.warn(
'The field_name keyword argument to earliest() and latest() '
'is deprecated in favor of passing positional arguments.',
RemovedInDjango30Warning,
)
order_by = (field_name,)
elif fields:
order_by = fields order_by = fields
else: else:
order_by = getattr(self.model._meta, 'get_latest_by') order_by = getattr(self.model._meta, 'get_latest_by')
@ -642,11 +631,11 @@ class QuerySet:
obj.query.add_ordering(*order_by) obj.query.add_ordering(*order_by)
return obj.get() return obj.get()
def earliest(self, *fields, field_name=None): def earliest(self, *fields):
return self._earliest(*fields, field_name=field_name) return self._earliest(*fields)
def latest(self, *fields, field_name=None): def latest(self, *fields):
return self.reverse()._earliest(*fields, field_name=field_name) return self.reverse()._earliest(*fields)
def first(self): def first(self):
"""Return the first object of a query or None if no match is found.""" """Return the first object of a query or None if no match is found."""

View File

@ -247,6 +247,9 @@ to remove usage of these features.
* Support for the ``context`` argument of ``Field.from_db_value()`` and * Support for the ``context`` argument of ``Field.from_db_value()`` and
``Expression.convert_value()`` is removed. ``Expression.convert_value()`` is removed.
* The ``field_name`` keyword argument of ``QuerySet.earliest()` and
``latest()`` is removed.
See :ref:`deprecated-features-2.1` for details on these changes, including how See :ref:`deprecated-features-2.1` for details on these changes, including how
to remove usage of these features. to remove usage of these features.

View File

@ -1,7 +1,6 @@
from datetime import datetime from datetime import datetime
from django.test import TestCase from django.test import TestCase
from django.utils.deprecation import RemovedInDjango30Warning
from .models import Article, IndexErrorArticle, Person from .models import Article, IndexErrorArticle, Person
@ -82,11 +81,6 @@ class EarliestOrLatestTests(TestCase):
Article.objects.model._meta.get_latest_by = ('pub_date', 'expire_date') Article.objects.model._meta.get_latest_by = ('pub_date', 'expire_date')
self.assertEqual(Article.objects.filter(pub_date=datetime(2005, 7, 28)).earliest(), a4) self.assertEqual(Article.objects.filter(pub_date=datetime(2005, 7, 28)).earliest(), a4)
def test_earliest_fields_and_field_name(self):
msg = 'Cannot use both positional arguments and the field_name keyword argument.'
with self.assertRaisesMessage(ValueError, msg):
Article.objects.earliest('pub_date', field_name='expire_date')
def test_latest(self): def test_latest(self):
# Because no Articles exist yet, latest() raises ArticleDoesNotExist. # Because no Articles exist yet, latest() raises ArticleDoesNotExist.
with self.assertRaises(Article.DoesNotExist): with self.assertRaises(Article.DoesNotExist):
@ -149,11 +143,6 @@ class EarliestOrLatestTests(TestCase):
Article.objects.model._meta.get_latest_by = ('pub_date', 'expire_date') Article.objects.model._meta.get_latest_by = ('pub_date', 'expire_date')
self.assertEqual(Article.objects.filter(pub_date=datetime(2005, 7, 27)).latest(), a3) self.assertEqual(Article.objects.filter(pub_date=datetime(2005, 7, 27)).latest(), a3)
def test_latest_fields_and_field_name(self):
msg = 'Cannot use both positional arguments and the field_name keyword argument.'
with self.assertRaisesMessage(ValueError, msg):
Article.objects.latest('pub_date', field_name='expire_date')
def test_latest_manual(self): def test_latest_manual(self):
# You can still use latest() with a model that doesn't have # You can still use latest() with a model that doesn't have
# "get_latest_by" set -- just pass in the field name manually. # "get_latest_by" set -- just pass in the field name manually.
@ -167,15 +156,6 @@ class EarliestOrLatestTests(TestCase):
Person.objects.latest() Person.objects.latest()
self.assertEqual(Person.objects.latest("birthday"), p2) self.assertEqual(Person.objects.latest("birthday"), p2)
def test_field_name_kwarg_deprecation(self):
Person.objects.create(name='Deprecator', birthday=datetime(1950, 1, 1))
msg = (
'The field_name keyword argument to earliest() and latest() '
'is deprecated in favor of passing positional arguments.'
)
with self.assertWarnsMessage(RemovedInDjango30Warning, msg):
Person.objects.latest(field_name='birthday')
class TestFirstLast(TestCase): class TestFirstLast(TestCase):