1
0
mirror of https://github.com/django/django.git synced 2025-04-14 20:34:36 +00:00

magic-removal: Added support for QuerySet.latest() and Manager.latest(), and updated unit tests.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2260 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-02-04 00:07:03 +00:00
parent ee05e42a36
commit cbc144b375
4 changed files with 56 additions and 30 deletions

View File

@ -126,12 +126,7 @@ class ManyRelatedObjectsDescriptor(object):
else:
manager.core_filters = {'%s__%s__exact' % (rel_field.name, instance_type._meta.pk.name): instance._get_pk_val()}
# Prepare the manager.
# TODO: Fix this hack?
# We're setting manager.model here because manager._prepare() expects
# that manager.model is set. This is slightly hackish.
manager.model = self.related.model
manager._prepare()
return manager
@ -194,13 +189,7 @@ class ReverseManyRelatedObjectsDescriptor(object):
add.alters_data = True
manager = RelatedManager()
# Prepare the manager.
# TODO: Fix this hack?
# We're setting manager.model here because manager._prepare() expects
# that manager.model is set. This is slightly hackish.
manager.model = self.rel_model
manager._prepare()
return manager

View File

@ -16,7 +16,6 @@ def ensure_default_manager(sender):
if hasattr(cls, 'objects'):
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name
cls.add_to_class('objects', Manager())
cls.objects._prepare()
dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)
@ -31,23 +30,13 @@ class Manager(object):
Manager.creation_counter += 1
self.model = None
def _prepare(self):
if self.model._meta.get_latest_by:
self.get_latest = self.__get_latest
def contribute_to_class(self, model, name):
# TODO: Use weakref because of possible memory leak / circular reference.
self.model = model
dispatcher.connect(self._prepare, signal=signals.class_prepared, sender=model)
setattr(model, name, ManagerDescriptor(self))
if not hasattr(model, '_default_manager') or self.creation_counter < model._default_manager.creation_counter:
model._default_manager = self
def __get_latest(self, *args, **kwargs):
kwargs['order_by'] = ('-' + self.model._meta.get_latest_by,)
kwargs['limit'] = 1
return self.get_object(*args, **kwargs)
#######################
# PROXIES TO QUERYSET #
#######################
@ -89,6 +78,9 @@ class Manager(object):
def iterator(self, *args, **kwargs):
return self.get_query_set().iterator(*args, **kwargs)
def latest(self, *args, **kwargs):
return self.get_query_set().latest(*args, **kwargs)
def order_by(self, *args, **kwargs):
return self.get_query_set().order_by(*args, **kwargs)

View File

@ -162,6 +162,15 @@ class QuerySet(object):
assert len(obj_list) == 1, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs)
return obj_list[0]
def latest(self, field_name=None):
"""
Returns the latest object, according to the model's 'get_latest_by'
option or optional given field_name.
"""
latest_by = field_name or self.model._meta.get_latest_by
assert bool(latest_by), "latest() requires either a field_name parameter or 'get_latest_by' in the model"
return self._clone(_limit=1, _order_by=('-'+latest_by,)).get()
def delete(self, *args, **kwargs):
"""
Deletes the records with the given kwargs. If no kwargs are given,

View File

@ -12,32 +12,68 @@ from django.db import models
class Article(models.Model):
headline = models.CharField(maxlength=100)
pub_date = models.DateTimeField()
pub_date = models.DateField()
expire_date = models.DateField()
class Meta:
get_latest_by = 'pub_date'
def __repr__(self):
return self.headline
class Person(models.Model):
name = models.CharField(maxlength=30)
birthday = models.DateField()
# Note that this model doesn't have "get_latest_by" set.
def __repr__(self):
return self.name
API_TESTS = """
# Because no Articles exist yet, get_latest() raises ArticleDoesNotExist.
>>> Article.objects.get_latest()
>>> Article.objects.latest()
Traceback (most recent call last):
...
DoesNotExist: Article does not exist for {'order_by': ('-pub_date',), 'limit': 1}
DoesNotExist: Article does not exist for ...
# Create a couple of Articles.
>>> from datetime import datetime
>>> a1 = Article(id=None, headline='Article 1', pub_date=datetime(2005, 7, 26))
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26), expire_date=datetime(2005, 9, 1))
>>> a1.save()
>>> a2 = Article(id=None, headline='Article 2', pub_date=datetime(2005, 7, 27))
>>> a2 = Article(headline='Article 2', pub_date=datetime(2005, 7, 27), expire_date=datetime(2005, 7, 28))
>>> a2.save()
>>> a3 = Article(id=None, headline='Article 3', pub_date=datetime(2005, 7, 27))
>>> a3 = Article(headline='Article 3', pub_date=datetime(2005, 7, 27), expire_date=datetime(2005, 8, 27))
>>> a3.save()
>>> a4 = Article(id=None, headline='Article 4', pub_date=datetime(2005, 7, 28))
>>> a4 = Article(headline='Article 4', pub_date=datetime(2005, 7, 28), expire_date=datetime(2005, 7, 30))
>>> a4.save()
# Get the latest Article.
>>> Article.objects.get_latest()
>>> Article.objects.latest()
Article 4
# Get the latest Article that matches certain filters.
>>> Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest()
Article 1
# Pass a custom field name to latest() to change the field that's used to
# determine the latest object.
>>> Article.objects.latest('expire_date')
Article 1
>>> Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date')
Article 3
# You can still use latest() with a model that doesn't have "get_latest_by"
# set -- just pass in the field name manually.
>>> p1 = Person(name='Ralph', birthday=datetime(1950, 1, 1))
>>> p1.save()
>>> p2 = Person(name='Stephanie', birthday=datetime(1960, 2, 3))
>>> p2.save()
>>> Person.objects.latest()
Traceback (most recent call last):
...
AssertionError: latest() requires either a field_name parameter or 'get_latest_by' in the model
>>> Person.objects.latest('birthday')
Stephanie
"""