the tests are shared with contenttypestests and so shouldn t import or reference any models directly subclasses should inherit django test testcase hook to allow subclasses to run these tests with alternate models answers will always be ordered in the order they were inserted we can retrieve the answers related to a particular object in the order they were created once we have a particular object we can retrieve the ordering of the queryset from a particular item it doesn t matter which answer we use to check the order it will always be the same an answer that s not related isn t updated q self question objects createtextother a self answer objects createtextnumber five questionq self q1 setanswerordero pk for o in self q1 answerset all a pk self assertequalself answer objects getpka pk order 0 def testchangeorderingself the ordering can be altered a self answer objects createtextnumber five questionself q1 swap the last two items in the order list idlist o pk for o in self q1 answerset all x idlist pop idlist insert1 x by default the ordering is different from the swapped version self assertnotequallista question getanswerorder idlist change the ordering to the swapped version this changes the ordering of the queryset a question setanswerorderidlist self assertquerysetequal self q1 answerset all john paul george number five ringo attrgettertext def testrecursiveorderingself p1 self post objects createtitle1 p2 self post objects createtitle2 p11 self post objects createtitle1 1 parentp1 p12 self post objects createtitle1 2 parentp1 self post objects createtitle2 1 parentp2 p13 self post objects createtitle1 3 parentp1 self assertsequenceequalp1 getpostorder p11 pk p12 pk p13 pk def testdeleteandinsertself q1 self question objects createtextwhat is your favorite color q2 self question objects createtextwhat color is it a1 self answer objects createtextblue questionq1 a2 self answer objects createtextred questionq1 a3 self answer objects createtextgreen questionq1 a4 self answer objects createtextyellow questionq1 self assertsequenceequalq1 answerset all a1 a2 a3 a4 a3 question q2 a3 save a1 delete newanswer self answer objects createtextblack questionq1 self assertsequenceequalq1 answerset all a2 a4 newanswer def testdatabaseroutingself class writetootherrouter def dbforwriteself model hints return other with self settingsdatabaserouterswritetootherrouter with self assertnumqueries0 usingdefault self assertnumqueries 1 usingother self q1 setanswerorder3 1 2 4 hook to allow subclasses to run these tests with alternate models answers will always be ordered in the order they were inserted we can retrieve the answers related to a particular object in the order they were created once we have a particular object we can retrieve the ordering of the queryset from a particular item it doesn t matter which answer we use to check the order it will always be the same an answer that s not related isn t updated the ordering can be altered swap the last two items in the order list by default the ordering is different from the swapped version change the ordering to the swapped version this changes the ordering of the queryset
from operator import attrgetter


class BaseOrderWithRespectToTests:
    databases = {"default", "other"}

    
    Answer = None
    Post = None
    Question = None

    @classmethod
    def setUpTestData(cls):
        cls.q1 = cls.Question.objects.create(
            text="Which Beatle starts with the letter 'R'?"
        )
        cls.Answer.objects.create(text="John", question=cls.q1)
        cls.Answer.objects.create(text="Paul", question=cls.q1)
        cls.Answer.objects.create(text="George", question=cls.q1)
        cls.Answer.objects.create(text="Ringo", question=cls.q1)

    def test_default_to_insertion_order(self):
        
        self.assertQuerySetEqual(
            self.q1.answer_set.all(),
            [
                "John",
                "Paul",
                "George",
                "Ringo",
            ],
            attrgetter("text"),
        )

    def test_previous_and_next_in_order(self):
        
        
        a1 = self.q1.answer_set.all()[0]
        self.assertEqual(a1.text, "John")
        self.assertEqual(a1.get_next_in_order().text, "Paul")

        a2 = list(self.q1.answer_set.all())[-1]
        self.assertEqual(a2.text, "Ringo")
        self.assertEqual(a2.get_previous_in_order().text, "George")

    def test_item_ordering(self):
        
        a1 = self.q1.answer_set.all()[1]
        id_list = [o.pk for o in self.q1.answer_set.all()]
        self.assertSequenceEqual(a1.question.get_answer_order(), id_list)

        
        
        a2 = self.Answer.objects.create(text="Number five", question=self.q1)
        self.assertEqual(
            list(a1.question.get_answer_order()), list(a2.question.get_answer_order())
        )

    def test_set_order_unrelated_object(self):
        
        q = self.Question.objects.create(text="other")
        a = self.Answer.objects.create(text="Number five", question=q)
        self.q1.set_answer_order([o.pk for o in self.q1.answer_set.all()] + [a.pk])
        self.assertEqual(self.Answer.objects.get(pk=a.pk)._order, 0)

    def test_change_ordering(self):
        
        a = self.Answer.objects.create(text="Number five", question=self.q1)

        
        id_list = [o.pk for o in self.q1.answer_set.all()]
        x = id_list.pop()
        id_list.insert(-1, x)

        
        self.assertNotEqual(list(a.question.get_answer_order()), id_list)

        
        
        a.question.set_answer_order(id_list)
        self.assertQuerySetEqual(
            self.q1.answer_set.all(),
            ["John", "Paul", "George", "Number five", "Ringo"],
            attrgetter("text"),
        )

    def test_recursive_ordering(self):
        p1 = self.Post.objects.create(title="1")
        p2 = self.Post.objects.create(title="2")
        p1_1 = self.Post.objects.create(title="1.1", parent=p1)
        p1_2 = self.Post.objects.create(title="1.2", parent=p1)
        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])

    def test_database_routing(self):
        class WriteToOtherRouter:
            def db_for_write(self, model, **hints):
                return "other"

        with self.settings(DATABASE_ROUTERS=[WriteToOtherRouter()]):
            with self.assertNumQueries(0, using="default"), self.assertNumQueries(
                1,
                using="other",
            ):
                self.q1.set_answer_order([3, 1, 2, 4])