Ticket #13296: 13296.diff

File 13296.diff, 5.6 KB (added by Simon Meers, 8 years ago)
  • django/db/models/base.py

    diff -r 548df236b2cc django/db/models/base.py
    a b  
    1717from django.db.models.query_utils import DeferredAttribute
    1818from django.db.models.deletion import Collector
    1919from django.db.models.options import Options
     20from django.db.models.aggregates import Max
    2021from django.db.models import signals
    2122from django.db.models.loading import register_models, get_model
    2223from django.utils.translation import ugettext_lazy as _
     
    2425from django.utils.encoding import smart_str, force_unicode
    2526from django.utils.text import get_text_list, capfirst
    2627
    27 
    2828class ModelBase(type):
    2929    """
    3030    Metaclass for all models.
     
    229229        opts._prepare(cls)
    230230
    231231        if opts.order_with_respect_to:
    232             cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
    233             cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
     232            cls.get_next_in_order = curry(
     233                cls._get_next_or_previous_in_order, is_next=True)
     234            cls.get_previous_in_order = curry(
     235                cls._get_next_or_previous_in_order, is_next=False)
    234236            # defer creating accessors on the foreign class until we are
    235237            # certain it has been created
    236238            def make_foreign_order_accessors(field, model, cls):
     
    537539                    # If this is a model with an order_with_respect_to
    538540                    # autopopulate the _order field
    539541                    field = meta.order_with_respect_to
    540                     order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
    541                     self._order = order_value
     542                    max_order_value = manager.using(using).filter(
     543                        **{field.name: getattr(self, field.attname)}).aggregate(
     544                        Max('_order'))['_order__max']
     545                    self._order = (max_order_value or 0) + 1
    542546
    543547                if not pk_set:
    544548                    if force_update:
  • tests/modeltests/order_with_respect_to/tests.py

    diff -r 548df236b2cc tests/modeltests/order_with_respect_to/tests.py
    a b  
    22
    33from django.test import TestCase
    44
    5 from models import Post, Question, Answer
     5from .models import Post, Question, Answer
    66
    77
    88class OrderWithRespectToTests(TestCase):
    99    def test_basic(self):
    1010        q1 = Question.objects.create(text="Which Beatle starts with the letter 'R'?")
    1111        q2 = Question.objects.create(text="What is your name?")
    12        
     12
    1313        Answer.objects.create(text="John", question=q1)
    1414        Answer.objects.create(text="Jonno", question=q2)
    1515        Answer.objects.create(text="Paul", question=q1)
    1616        Answer.objects.create(text="Paulo", question=q2)
    1717        Answer.objects.create(text="George", question=q1)
    1818        Answer.objects.create(text="Ringo", question=q1)
    19        
     19
    2020        # The answers will always be ordered in the order they were inserted.
    2121        self.assertQuerysetEqual(
    2222            q1.answer_set.all(), [
     
    2424            ],
    2525            attrgetter("text"),
    2626        )
    27        
     27
    2828        # We can retrieve the answers related to a particular object, in the
    2929        # order they were created, once we have a particular object.
    3030        a1 = Answer.objects.filter(question=q1)[0]
     
    3434        a4 = list(Answer.objects.filter(question=q1))[-1]
    3535        self.assertEqual(a4.text, "Ringo")
    3636        self.assertEqual(a4.get_previous_in_order().text, "George")
    37        
     37
    3838        # Determining (and setting) the ordering for a particular item is also
    3939        # possible.
    4040        id_list = [o.pk for o in q1.answer_set.all()]
    4141        self.assertEqual(a2.question.get_answer_order(), id_list)
    42        
     42
    4343        a5 = Answer.objects.create(text="Number five", question=q1)
    44        
     44
    4545        # It doesn't matter which answer we use to check the order, it will
    4646        # always be the same.
    4747        self.assertEqual(
    4848            a2.question.get_answer_order(), a5.question.get_answer_order()
    4949        )
    50        
     50
    5151        # The ordering can be altered:
    5252        id_list = [o.pk for o in q1.answer_set.all()]
    5353        x = id_list.pop()
     
    6969        p2_1 = Post.objects.create(title="2.1", parent=p2)
    7070        p1_3 = Post.objects.create(title="1.3", parent=p1)
    7171        self.assertEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk])
     72
     73    def test_deletion_and_insertion(self):
     74        """ Regression test for https://code.djangoproject.com/ticket/13296 """
     75        q1 = Question.objects.create(text="Which Beatle starts with the letter 'R'?")
     76        q2 = Question.objects.create(text="What is your name?")
     77        a1 = Answer.objects.create(text="John", question=q1)
     78        a2 = Answer.objects.create(text="Paul", question=q1)
     79        a3 = Answer.objects.create(text="George", question=q1)
     80        a4 = Answer.objects.create(text="Ringo", question=q1)
     81        self.assertQuerysetEqual(
     82            q1.answer_set.all(), ["John", "Paul", "George", "Ringo",],
     83            attrgetter("text"))
     84
     85        # delete/move some entries
     86        a2.delete()
     87        a3.question = q2
     88        a3.save()
     89        self.assertQuerysetEqual(
     90            q1.answer_set.all(), ["John", "Ringo",], attrgetter("text"))
     91
     92        # insert a new one and see if it lands at the end
     93        a5 = Answer.objects.create(text="Guido", question=q1)
     94        self.assertQuerysetEqual(
     95            q1.answer_set.all(), ["John", "Ringo", "Guido"], attrgetter("text"))
Back to Top