Kaydet (Commit) 6d9f061b authored tarafından Tim Graham's avatar Tim Graham

[1.8.x] Fixed #25786 -- Fixed set_FOO_order() crash with order_with_respect_to…

[1.8.x] Fixed #25786 -- Fixed set_FOO_order() crash with order_with_respect_to referencing OneToOneField pk.

Partial backport of 7bec480f from master
üst 8f724817
...@@ -1674,13 +1674,13 @@ class Model(six.with_metaclass(ModelBase)): ...@@ -1674,13 +1674,13 @@ class Model(six.with_metaclass(ModelBase)):
def method_set_order(ordered_obj, self, id_list, using=None): def method_set_order(ordered_obj, self, id_list, using=None):
if using is None: if using is None:
using = DEFAULT_DB_ALIAS using = DEFAULT_DB_ALIAS
rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) order_wrt = ordered_obj._meta.order_with_respect_to
order_name = ordered_obj._meta.order_with_respect_to.name filter_args = order_wrt.get_forward_related_filter(self)
# FIXME: It would be nice if there was an "update many" version of update # FIXME: It would be nice if there was an "update many" version of update
# for situations like this. # for situations like this.
with transaction.atomic(using=using, savepoint=False): with transaction.atomic(using=using, savepoint=False):
for i, j in enumerate(id_list): for i, j in enumerate(id_list):
ordered_obj.objects.filter(**{'pk': j, order_name: rel_val}).update(_order=i) ordered_obj.objects.filter(pk=j, **filter_args).update(_order=i)
def method_get_order(ordered_obj, self): def method_get_order(ordered_obj, self):
......
...@@ -314,6 +314,19 @@ class RelatedField(Field): ...@@ -314,6 +314,19 @@ class RelatedField(Field):
else: else:
self.do_related_class(other, cls) self.do_related_class(other, cls)
def get_forward_related_filter(self, obj):
"""
Return the keyword arguments that when supplied to
self.model.object.filter(), would select all instances related through
this field to the remote obj. This is used to build the querysets
returned by related descriptors. obj is an instance of
self.related_field.model.
"""
return {
'%s__%s' % (self.name, rh_field.name): getattr(obj, rh_field.attname)
for _, rh_field in self.related_fields
}
@property @property
def swappable_setting(self): def swappable_setting(self):
""" """
......
...@@ -42,3 +42,7 @@ Bugfixes ...@@ -42,3 +42,7 @@ Bugfixes
* Fixed a duplicate query regression in 1.8 on proxied model deletion * Fixed a duplicate query regression in 1.8 on proxied model deletion
(:ticket:`25685`). (:ticket:`25685`).
* Fixed ``set_FOO_order()`` crash when the ``ForeignKey`` of a model with
``order_with_respect_to`` references a model with a ``OneToOneField``
primary key (:ticket:`25786`).
...@@ -33,3 +33,19 @@ class Post(models.Model): ...@@ -33,3 +33,19 @@ class Post(models.Model):
def __str__(self): def __str__(self):
return self.title return self.title
# order_with_respect_to points to a model with a OneToOneField primary key.
class Entity(models.Model):
pass
class Dimension(models.Model):
entity = models.OneToOneField('Entity', primary_key=True)
class Component(models.Model):
dimension = models.ForeignKey('Dimension')
class Meta:
order_with_respect_to = 'dimension'
...@@ -5,7 +5,7 @@ from operator import attrgetter ...@@ -5,7 +5,7 @@ from operator import attrgetter
from django.db import models from django.db import models
from django.test import TestCase from django.test import TestCase
from .models import Answer, Post, Question from .models import Answer, Dimension, Entity, Post, Question
class OrderWithRespectToTests(TestCase): class OrderWithRespectToTests(TestCase):
...@@ -103,3 +103,13 @@ class OrderWithRespectToTests2(TestCase): ...@@ -103,3 +103,13 @@ class OrderWithRespectToTests2(TestCase):
count += 1 count += 1
self.assertEqual(count, 1) self.assertEqual(count, 1)
class TestOrderWithRespectToOneToOnePK(TestCase):
def test_set_order(self):
e = Entity.objects.create()
d = Dimension.objects.create(entity=e)
c1 = d.component_set.create()
c2 = d.component_set.create()
d.set_component_order([c1.id, c2.id])
self.assertQuerysetEqual(d.component_set.all(), [c1.id, c2.id], attrgetter('pk'))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment