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:
parent
ee05e42a36
commit
cbc144b375
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user