Ticket #17813: t17813.4.diff
File t17813.4.diff, 16.8 KB (added by , 13 years ago) |
---|
-
django/db/models/manager.py
diff --git a/django/db/models/manager.py b/django/db/models/manager.py index e1bbf6e..abff034 100644
a b def ensure_default_manager(sender, **kwargs): 42 42 43 43 signals.class_prepared.connect(ensure_default_manager) 44 44 45 45 46 class Manager(object): 46 47 # Tracks each time a Manager instance is created. Used to retain order. 47 48 creation_counter = 0 … … class Manager(object): 160 161 def iterator(self, *args, **kwargs): 161 162 return self.get_query_set().iterator(*args, **kwargs) 162 163 164 def earliest(self, *args, **kwargs): 165 return self.get_query_set().earliest(*args, **kwargs) 166 163 167 def latest(self, *args, **kwargs): 164 168 return self.get_query_set().latest(*args, **kwargs) 165 169 … … class Manager(object): 208 212 def raw(self, raw_query, params=None, *args, **kwargs): 209 213 return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self._db, *args, **kwargs) 210 214 215 211 216 class ManagerDescriptor(object): 212 217 # This class ensures managers aren't accessible via model instances. 213 218 # For example, Poll.objects works, but poll_obj.objects raises AttributeError. … … class ManagerDescriptor(object): 219 224 raise AttributeError("Manager isn't accessible via %s instances" % type.__name__) 220 225 return self.manager 221 226 227 222 228 class EmptyManager(Manager): 223 229 def get_query_set(self): 224 230 return self.get_empty_query_set() -
django/db/models/query.py
diff --git a/django/db/models/query.py b/django/db/models/query.py index 44acadf..d1319d0 100644
a b REPR_OUTPUT_SIZE = 20 25 25 # Pull into this namespace for backwards compatibility. 26 26 EmptyResultSet = sql.EmptyResultSet 27 27 28 28 29 class QuerySet(object): 29 30 """ 30 31 Represents a lazy database lookup for a set of objects. … … class QuerySet(object): 458 459 # Re-raise the IntegrityError with its original traceback. 459 460 raise exc_info[1], None, exc_info[2] 460 461 461 def latest(self, field_name=None):462 def _earliest_or_latest(self, field_name=None, direction="-"): 462 463 """ 463 Returns the latest object, according to the model's 'get_latest_by'464 option or optional given field_name.464 Returns the latest object, according to the model's 465 'get_latest_by' option or optional given field_name. 465 466 """ 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" 467 order_by = field_name or getattr(self.model._meta, 'get_latest_by') 468 assert bool(order_by), "_earliest_or_latest() requires either a "\ 469 "field_name parameter or 'get_latest_by' in the model" 468 470 assert self.query.can_filter(), \ 469 471 "Cannot change a query once a slice has been taken." 470 472 obj = self._clone() 471 473 obj.query.set_limits(high=1) 472 474 obj.query.clear_ordering() 473 obj.query.add_ordering(' -%s' % latest_by)475 obj.query.add_ordering('%s%s' % (direction, order_by)) 474 476 return obj.get() 475 477 478 def earliest(self, field_name=None): 479 return self._earliest_or_latest(field_name=field_name, direction="") 480 481 def latest(self, field_name=None): 482 return self._earliest_or_latest(field_name=field_name, direction="-") 483 476 484 def in_bulk(self, id_list): 477 485 """ 478 486 Returns a dictionary mapping each of the given IDs to the object with … … class EmptyQuerySet(QuerySet): 1237 1245 # situations). 1238 1246 value_annotation = False 1239 1247 1248 1240 1249 def get_klass_info(klass, max_depth=0, cur_depth=0, requested=None, 1241 1250 only_load=None, local_only=False): 1242 1251 """ -
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. 78 78 setting, if set. If the backend doesn't support tablespaces, this option is 79 79 ignored. 80 80 81 81 82 ``get_latest_by`` 82 83 ----------------- 83 84 -
docs/ref/models/querysets.txt
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index b20c6e3..3664e61 100644
a b This example returns the latest ``Entry`` in the table, according to the 1466 1466 1467 1467 If your model's :ref:`Meta <meta-options>` specifies 1468 1468 :attr:`~django.db.models.Options.get_latest_by`, you can leave off the 1469 ``field_name`` argument to `` latest()``. Django will use the field specified1470 in :attr:`~django.db.models.Options.get_latest_by` by default.1469 ``field_name`` argument to ``earliest()`` or ``latest()``. Django will use the 1470 field specified in :attr:`~django.db.models.Options.get_latest_by` by default. 1471 1471 1472 Like :meth:`get()`, `` latest()`` raises1473 :exc:`~django.core.exceptions.DoesNotExist` if there is no object with the given1474 parameters.1472 Like :meth:`get()`, ``earliest()`` and ``latest()`` raise 1473 :exc:`~django.core.exceptions.DoesNotExist` if there is no object with the 1474 given parameters. 1475 1475 1476 Note ``latest()`` exists purely for convenience and readability. 1476 Note that ``earliest()`` and ``latest()`` exist purely for convenience and 1477 readability. 1477 1478 1478 1479 aggregate 1479 1480 ~~~~~~~~~ -
docs/topics/db/models.txt
diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt index ee6644f..586820e 100644
a b right). 983 983 984 984 So a child model does not have access to its parent's :ref:`Meta 985 985 <meta-options>` class. However, there are a few limited cases where the child 986 inherits behavior from the parent: if the child does not specify an 987 :attr:`~django.db.models.Options.ordering` attribute or a988 :attr:`~django.db.models.Options.get_latest_by` attribute, it will inherit989 these from its parent.986 inherits behavior from the parent: if the child does not specify an attribute 987 :attr:`~django.db.models.Options.ordering` or 988 :attr:`~django.db.models.Options.get_latest_by`, 989 , it will inherit these from its parent. 990 990 991 991 If the parent has an ordering and you don't want the child to have any natural 992 992 ordering, you can explicitly disable it:: -
new file tests/modeltests/get_earliest_or_latest/models.py
diff --git a/tests/modeltests/get_earliest_or_latest/.models.py.swp b/tests/modeltests/get_earliest_or_latest/.models.py.swp new file mode 100644 index 0000000..53ea145 Binary files /dev/null and b/tests/modeltests/get_earliest_or_latest/.models.py.swp differ diff --git a/tests/modeltests/get_earliest_or_latest/.tests.py.swp b/tests/modeltests/get_earliest_or_latest/.tests.py.swp new file mode 100644 index 0000000..d33e29f Binary files /dev/null and b/tests/modeltests/get_earliest_or_latest/.tests.py.swp differ 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 """ 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 25 class 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..bd27e13
- + 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 EarliestOrLatestTests(TestCase): 11 """Tests for the earliest() and latest() objects methods""" 12 13 def tearDown(self): 14 """Makes sure Article has a get_latest_by""" 15 if not Article._meta.get_latest_by: 16 Article._meta.get_latest_by = 'pub_date' 17 18 def test_earliest(self): 19 # Because no Articles exist yet, earliest() raises ArticleDoesNotExist. 20 self.assertRaises(Article.DoesNotExist, Article.objects.earliest) 21 22 a1 = Article.objects.create( 23 headline="Article 1", pub_date=datetime(2005, 7, 26), 24 expire_date=datetime(2005, 9, 1) 25 ) 26 a2 = Article.objects.create( 27 headline="Article 2", pub_date=datetime(2005, 7, 27), 28 expire_date=datetime(2005, 7, 28) 29 ) 30 a3 = Article.objects.create( 31 headline="Article 3", pub_date=datetime(2005, 7, 28), 32 expire_date=datetime(2005, 8, 27) 33 ) 34 a4 = Article.objects.create( 35 headline="Article 4", pub_date=datetime(2005, 7, 28), 36 expire_date=datetime(2005, 7, 30) 37 ) 38 39 # Get the earliest Article. 40 self.assertEqual(Article.objects.earliest(), a1) 41 # Get the earliest Article that matches certain filters. 42 self.assertEqual( 43 Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).earliest(), 44 a2 45 ) 46 47 # Pass a custom field name to earliest() to change the field that's used 48 # to determine the earliest object. 49 self.assertEqual(Article.objects.earliest('expire_date'), a2) 50 self.assertEqual(Article.objects.filter( 51 pub_date__gt=datetime(2005, 7, 26)).earliest('expire_date'), a2) 52 53 # Ensure that earliest() overrides any other ordering specified on the 54 # query. Refs #11283. 55 self.assertEqual(Article.objects.order_by('id').earliest(), a1) 56 57 # Ensure that error is raised if the user forgot to add a get_latest_by 58 # in the Model.Meta 59 Article.objects.model._meta.get_latest_by = None 60 self.assertRaisesMessage( 61 AssertionError, 62 "_earliest_or_latest() requires either a field_name parameter or "\ 63 "'get_latest_by' in the model", 64 lambda: Article.objects.earliest(), 65 ) 66 67 68 def test_latest(self): 69 # Because no Articles exist yet, latest() raises ArticleDoesNotExist. 70 self.assertRaises(Article.DoesNotExist, Article.objects.latest) 71 72 a1 = Article.objects.create( 73 headline="Article 1", pub_date=datetime(2005, 7, 26), 74 expire_date=datetime(2005, 9, 1) 75 ) 76 a2 = Article.objects.create( 77 headline="Article 2", pub_date=datetime(2005, 7, 27), 78 expire_date=datetime(2005, 7, 28) 79 ) 80 a3 = Article.objects.create( 81 headline="Article 3", pub_date=datetime(2005, 7, 27), 82 expire_date=datetime(2005, 8, 27) 83 ) 84 a4 = Article.objects.create( 85 headline="Article 4", pub_date=datetime(2005, 7, 28), 86 expire_date=datetime(2005, 7, 30) 87 ) 88 89 # Get the latest Article. 90 self.assertEqual(Article.objects.latest(), a4) 91 # Get the latest Article that matches certain filters. 92 self.assertEqual( 93 Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest(), 94 a1 95 ) 96 97 # Pass a custom field name to latest() to change the field that's used 98 # to determine the latest object. 99 self.assertEqual(Article.objects.latest('expire_date'), a1) 100 self.assertEqual( 101 Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date'), 102 a3, 103 ) 104 105 # Ensure that latest() overrides any other ordering specified on the query. Refs #11283. 106 self.assertEqual(Article.objects.order_by('id').latest(), a4) 107 108 # Ensure that error is raised if the user forgot to add a get_latest_by 109 # in the Model.Meta 110 Article.objects.model._meta.get_latest_by = None 111 self.assertRaisesMessage( 112 AssertionError, 113 "_earliest_or_latest() requires either a field_name parameter or "\ 114 "'get_latest_by' in the model", 115 lambda: Article.objects.latest(), 116 ) 117 118 119 def test_latest_manual(self): 120 # You can still use latest() with a model that doesn't have 121 # "get_latest_by" set -- just pass in the field name manually. 122 p1 = Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1)) 123 p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3)) 124 self.assertRaises(AssertionError, Person.objects.latest) 125 126 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_by3 4 Models can have a ``get_latest_by`` attribute, which should be set to the name5 of a ``DateField`` or ``DateTimeField``. If ``get_latest_by`` exists, the6 model's manager will get a ``latest()`` method, which will return the latest7 object in the database according to that field. "Latest" means "having the date8 farthest into the future."9 """10 11 from django.db import models12 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.headline23 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_import2 3 from datetime import datetime4 5 from django.test import TestCase6 7 from .models import Article, Person8 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 a138 )39 40 # Pass a custom field name to latest() to change the field that's used41 # 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 have53 # "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)