Browse Source

Fixed #13296 -- Fixed ordering by Options.order_with_respect_to after deleting objects.

Thanks Simon Meers for the original patch.
Hasan Ramezani 5 years ago
parent
commit
f97bbad908
2 changed files with 24 additions and 4 deletions
  1. 10 4
      django/db/models/base.py
  2. 14 0
      tests/order_with_respect_to/base_tests.py

+ 10 - 4
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]

+ 14 - 0
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])