1. """
    
  2. The tests are shared with contenttypes_tests and so shouldn't import or
    
  3. reference any models directly. Subclasses should inherit django.test.TestCase.
    
  4. """
    
  5. from operator import attrgetter
    
  6. 
    
  7. 
    
  8. class BaseOrderWithRespectToTests:
    
  9.     databases = {"default", "other"}
    
  10. 
    
  11.     # Hook to allow subclasses to run these tests with alternate models.
    
  12.     Answer = None
    
  13.     Post = None
    
  14.     Question = None
    
  15. 
    
  16.     @classmethod
    
  17.     def setUpTestData(cls):
    
  18.         cls.q1 = cls.Question.objects.create(
    
  19.             text="Which Beatle starts with the letter 'R'?"
    
  20.         )
    
  21.         cls.Answer.objects.create(text="John", question=cls.q1)
    
  22.         cls.Answer.objects.create(text="Paul", question=cls.q1)
    
  23.         cls.Answer.objects.create(text="George", question=cls.q1)
    
  24.         cls.Answer.objects.create(text="Ringo", question=cls.q1)
    
  25. 
    
  26.     def test_default_to_insertion_order(self):
    
  27.         # Answers will always be ordered in the order they were inserted.
    
  28.         self.assertQuerysetEqual(
    
  29.             self.q1.answer_set.all(),
    
  30.             [
    
  31.                 "John",
    
  32.                 "Paul",
    
  33.                 "George",
    
  34.                 "Ringo",
    
  35.             ],
    
  36.             attrgetter("text"),
    
  37.         )
    
  38. 
    
  39.     def test_previous_and_next_in_order(self):
    
  40.         # We can retrieve the answers related to a particular object, in the
    
  41.         # order they were created, once we have a particular object.
    
  42.         a1 = self.q1.answer_set.all()[0]
    
  43.         self.assertEqual(a1.text, "John")
    
  44.         self.assertEqual(a1.get_next_in_order().text, "Paul")
    
  45. 
    
  46.         a2 = list(self.q1.answer_set.all())[-1]
    
  47.         self.assertEqual(a2.text, "Ringo")
    
  48.         self.assertEqual(a2.get_previous_in_order().text, "George")
    
  49. 
    
  50.     def test_item_ordering(self):
    
  51.         # We can retrieve the ordering of the queryset from a particular item.
    
  52.         a1 = self.q1.answer_set.all()[1]
    
  53.         id_list = [o.pk for o in self.q1.answer_set.all()]
    
  54.         self.assertSequenceEqual(a1.question.get_answer_order(), id_list)
    
  55. 
    
  56.         # It doesn't matter which answer we use to check the order, it will
    
  57.         # always be the same.
    
  58.         a2 = self.Answer.objects.create(text="Number five", question=self.q1)
    
  59.         self.assertEqual(
    
  60.             list(a1.question.get_answer_order()), list(a2.question.get_answer_order())
    
  61.         )
    
  62. 
    
  63.     def test_set_order_unrelated_object(self):
    
  64.         """An answer that's not related isn't updated."""
    
  65.         q = self.Question.objects.create(text="other")
    
  66.         a = self.Answer.objects.create(text="Number five", question=q)
    
  67.         self.q1.set_answer_order([o.pk for o in self.q1.answer_set.all()] + [a.pk])
    
  68.         self.assertEqual(self.Answer.objects.get(pk=a.pk)._order, 0)
    
  69. 
    
  70.     def test_change_ordering(self):
    
  71.         # The ordering can be altered
    
  72.         a = self.Answer.objects.create(text="Number five", question=self.q1)
    
  73. 
    
  74.         # Swap the last two items in the order list
    
  75.         id_list = [o.pk for o in self.q1.answer_set.all()]
    
  76.         x = id_list.pop()
    
  77.         id_list.insert(-1, x)
    
  78. 
    
  79.         # By default, the ordering is different from the swapped version
    
  80.         self.assertNotEqual(list(a.question.get_answer_order()), id_list)
    
  81. 
    
  82.         # Change the ordering to the swapped version -
    
  83.         # this changes the ordering of the queryset.
    
  84.         a.question.set_answer_order(id_list)
    
  85.         self.assertQuerysetEqual(
    
  86.             self.q1.answer_set.all(),
    
  87.             ["John", "Paul", "George", "Number five", "Ringo"],
    
  88.             attrgetter("text"),
    
  89.         )
    
  90. 
    
  91.     def test_recursive_ordering(self):
    
  92.         p1 = self.Post.objects.create(title="1")
    
  93.         p2 = self.Post.objects.create(title="2")
    
  94.         p1_1 = self.Post.objects.create(title="1.1", parent=p1)
    
  95.         p1_2 = self.Post.objects.create(title="1.2", parent=p1)
    
  96.         self.Post.objects.create(title="2.1", parent=p2)
    
  97.         p1_3 = self.Post.objects.create(title="1.3", parent=p1)
    
  98.         self.assertSequenceEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk])
    
  99. 
    
  100.     def test_delete_and_insert(self):
    
  101.         q1 = self.Question.objects.create(text="What is your favorite color?")
    
  102.         q2 = self.Question.objects.create(text="What color is it?")
    
  103.         a1 = self.Answer.objects.create(text="Blue", question=q1)
    
  104.         a2 = self.Answer.objects.create(text="Red", question=q1)
    
  105.         a3 = self.Answer.objects.create(text="Green", question=q1)
    
  106.         a4 = self.Answer.objects.create(text="Yellow", question=q1)
    
  107.         self.assertSequenceEqual(q1.answer_set.all(), [a1, a2, a3, a4])
    
  108.         a3.question = q2
    
  109.         a3.save()
    
  110.         a1.delete()
    
  111.         new_answer = self.Answer.objects.create(text="Black", question=q1)
    
  112.         self.assertSequenceEqual(q1.answer_set.all(), [a2, a4, new_answer])
    
  113. 
    
  114.     def test_database_routing(self):
    
  115.         class WriteToOtherRouter:
    
  116.             def db_for_write(self, model, **hints):
    
  117.                 return "other"
    
  118. 
    
  119.         with self.settings(DATABASE_ROUTERS=[WriteToOtherRouter()]):
    
  120.             with self.assertNumQueries(0, using="default"), self.assertNumQueries(
    
  121.                 1,
    
  122.                 using="other",
    
  123.             ):
    
  124.                 self.q1.set_answer_order([3, 1, 2, 4])