Fixed #13241. order_with_respect_to now works with ForeignKeys who refer to their model lazily (i.e. with a string). Thanks to Gabriel Grant for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14045 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Alex Gaynor 2010-10-08 23:54:43 +00:00
parent 5c5f1cfe70
commit ccc43508e3
4 changed files with 42 additions and 4 deletions

View File

@ -198,6 +198,7 @@ answer newbie questions, and generally made Django that much better:
David Gouldin <dgouldin@gmail.com> David Gouldin <dgouldin@gmail.com>
pradeep.gowda@gmail.com pradeep.gowda@gmail.com
Collin Grady <collin@collingrady.com> Collin Grady <collin@collingrady.com>
Gabriel Grant <g@briel.ca>
Simon Greenhill <dev@simon.net.nz> Simon Greenhill <dev@simon.net.nz>
Owen Griffiths Owen Griffiths
Espen Grindhaug <http://grindhaug.org/> Espen Grindhaug <http://grindhaug.org/>

View File

@ -5,7 +5,8 @@ import django.db.models.manager # Imported to register signal handler.
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS
from django.core import validators from django.core import validators
from django.db.models.fields import AutoField, FieldDoesNotExist from django.db.models.fields import AutoField, FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField from django.db.models.fields.related import (OneToOneRel, ManyToOneRel,
OneToOneField, add_lazy_relation)
from django.db.models.query import delete_objects, Q from django.db.models.query import delete_objects, Q
from django.db.models.query_utils import CollectedObjects, DeferredAttribute from django.db.models.query_utils import CollectedObjects, DeferredAttribute
from django.db.models.options import Options from django.db.models.options import Options
@ -223,8 +224,25 @@ class ModelBase(type):
if opts.order_with_respect_to: if opts.order_with_respect_to:
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True) cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False) cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls)) # defer creating accessors on the foreign class until we are
setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls)) # certain it has been created
def make_foreign_order_accessors(field, model, cls):
setattr(
field.rel.to,
'get_%s_order' % cls.__name__.lower(),
curry(method_get_order, cls)
)
setattr(
field.rel.to,
'set_%s_order' % cls.__name__.lower(),
curry(method_set_order, cls)
)
add_lazy_relation(
cls,
opts.order_with_respect_to,
opts.order_with_respect_to.rel.to,
make_foreign_order_accessors
)
# Give the class a docstring -- its definition. # Give the class a docstring -- its definition.
if cls.__doc__ is None: if cls.__doc__ is None:

View File

@ -17,3 +17,13 @@ class Answer(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.text) return unicode(self.text)
class Post(models.Model):
title = models.CharField(max_length=200)
parent = models.ForeignKey("self", related_name="children", null=True)
class Meta:
order_with_respect_to = "parent"
def __unicode__(self):
return self.title

View File

@ -2,7 +2,7 @@ from operator import attrgetter
from django.test import TestCase from django.test import TestCase
from models import Question, Answer from models import Post, Question, Answer
class OrderWithRespectToTests(TestCase): class OrderWithRespectToTests(TestCase):
@ -60,3 +60,12 @@ class OrderWithRespectToTests(TestCase):
], ],
attrgetter("text") attrgetter("text")
) )
def test_recursive_ordering(self):
p1 = Post.objects.create(title='1')
p2 = Post.objects.create(title='2')
p1_1 = Post.objects.create(title="1.1", parent=p1)
p1_2 = Post.objects.create(title="1.2", parent=p1)
p2_1 = Post.objects.create(title="2.1", parent=p2)
p1_3 = Post.objects.create(title="1.3", parent=p1)
self.assertEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk])