From f97bbad908df128189eff77d98af9a25ed1ecf23 Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Fri, 30 Aug 2019 10:28:18 +0200 Subject: [PATCH] Fixed #13296 -- Fixed ordering by Options.order_with_respect_to after deleting objects. Thanks Simon Meers for the original patch. --- django/db/models/base.py | 14 ++++++++++---- tests/order_with_respect_to/base_tests.py | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index 4f3145ebc26..3ce711f3f1a 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -15,13 +15,16 @@ from django.db import ( DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connection, 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.constraints import CheckConstraint, UniqueConstraint from django.db.models.deletion import CASCADE, Collector from django.db.models.fields.related import ( 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.options import Options from django.db.models.query import Q @@ -869,9 +872,12 @@ class Model(metaclass=ModelBase): # autopopulate the _order field field = meta.order_with_respect_to filter_args = field.get_filter_kwargs_for_object(self) - order_value = cls._base_manager.using(using).filter(**filter_args).count() - self._order = order_value - + self._order = cls._base_manager.using(using).filter(**filter_args).aggregate( + _order__max=Coalesce( + ExpressionWrapper(Max('_order') + Value(1), output_field=IntegerField()), + Value(0), + ), + )['_order__max'] fields = meta.local_concrete_fields if not pk_set: fields = [f for f in fields if f is not meta.auto_field] diff --git a/tests/order_with_respect_to/base_tests.py b/tests/order_with_respect_to/base_tests.py index be67b068def..a99b632436e 100644 --- a/tests/order_with_respect_to/base_tests.py +++ b/tests/order_with_respect_to/base_tests.py @@ -87,3 +87,17 @@ class BaseOrderWithRespectToTests: self.Post.objects.create(title="2.1", parent=p2) 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]) + + 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])