[3.0.x] Fixed #13296 -- Fixed ordering by Options.order_with_respect_to after deleting objects.

Thanks Simon Meers for the original patch.

Backport of f97bbad908 from master
This commit is contained in:
Hasan Ramezani 2019-08-30 10:28:18 +02:00 committed by Mariusz Felisiak
parent 368832e803
commit 2362f27265
2 changed files with 24 additions and 4 deletions

View File

@ -15,13 +15,16 @@ from django.db import (
DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connection, DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connection,
connections, router, transaction, connections, router, transaction,
) )
from django.db.models import NOT_PROVIDED from django.db.models import (
NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value,
)
from django.db.models.constants import LOOKUP_SEP from django.db.models.constants import LOOKUP_SEP
from django.db.models.constraints import CheckConstraint, UniqueConstraint from django.db.models.constraints import CheckConstraint, UniqueConstraint
from django.db.models.deletion import CASCADE, Collector from django.db.models.deletion import CASCADE, Collector
from django.db.models.fields.related import ( from django.db.models.fields.related import (
ForeignObjectRel, OneToOneField, lazy_related_operation, resolve_relation, ForeignObjectRel, OneToOneField, lazy_related_operation, resolve_relation,
) )
from django.db.models.functions import Coalesce
from django.db.models.manager import Manager from django.db.models.manager import Manager
from django.db.models.options import Options from django.db.models.options import Options
from django.db.models.query import Q from django.db.models.query import Q
@ -869,9 +872,12 @@ class Model(metaclass=ModelBase):
# autopopulate the _order field # autopopulate the _order field
field = meta.order_with_respect_to field = meta.order_with_respect_to
filter_args = field.get_filter_kwargs_for_object(self) filter_args = field.get_filter_kwargs_for_object(self)
order_value = cls._base_manager.using(using).filter(**filter_args).count() self._order = cls._base_manager.using(using).filter(**filter_args).aggregate(
self._order = order_value _order__max=Coalesce(
ExpressionWrapper(Max('_order') + Value(1), output_field=IntegerField()),
Value(0),
),
)['_order__max']
fields = meta.local_concrete_fields fields = meta.local_concrete_fields
if not pk_set: if not pk_set:
fields = [f for f in fields if f is not meta.auto_field] fields = [f for f in fields if f is not meta.auto_field]

View File

@ -87,3 +87,17 @@ class BaseOrderWithRespectToTests:
self.Post.objects.create(title="2.1", parent=p2) self.Post.objects.create(title="2.1", parent=p2)
p1_3 = self.Post.objects.create(title="1.3", parent=p1) p1_3 = self.Post.objects.create(title="1.3", parent=p1)
self.assertSequenceEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk]) self.assertSequenceEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk])
def test_delete_and_insert(self):
q1 = self.Question.objects.create(text='What is your favorite color?')
q2 = self.Question.objects.create(text='What color is it?')
a1 = self.Answer.objects.create(text='Blue', question=q1)
a2 = self.Answer.objects.create(text='Red', question=q1)
a3 = self.Answer.objects.create(text='Green', question=q1)
a4 = self.Answer.objects.create(text='Yellow', question=q1)
self.assertSequenceEqual(q1.answer_set.all(), [a1, a2, a3, a4])
a3.question = q2
a3.save()
a1.delete()
new_answer = self.Answer.objects.create(text='Black', question=q1)
self.assertSequenceEqual(q1.answer_set.all(), [a2, a4, new_answer])