1. import datetime
    
  2. from copy import deepcopy
    
  3. 
    
  4. from django.core.exceptions import FieldError, MultipleObjectsReturned
    
  5. from django.db import IntegrityError, models, transaction
    
  6. from django.test import TestCase
    
  7. from django.utils.translation import gettext_lazy
    
  8. 
    
  9. from .models import (
    
  10.     Article,
    
  11.     Category,
    
  12.     Child,
    
  13.     ChildNullableParent,
    
  14.     ChildStringPrimaryKeyParent,
    
  15.     City,
    
  16.     Country,
    
  17.     District,
    
  18.     First,
    
  19.     Parent,
    
  20.     ParentStringPrimaryKey,
    
  21.     Record,
    
  22.     Relation,
    
  23.     Reporter,
    
  24.     School,
    
  25.     Student,
    
  26.     Third,
    
  27.     ToFieldChild,
    
  28. )
    
  29. 
    
  30. 
    
  31. class ManyToOneTests(TestCase):
    
  32.     @classmethod
    
  33.     def setUpTestData(cls):
    
  34.         # Create a few Reporters.
    
  35.         cls.r = Reporter(first_name="John", last_name="Smith", email="[email protected]")
    
  36.         cls.r.save()
    
  37.         cls.r2 = Reporter(
    
  38.             first_name="Paul", last_name="Jones", email="[email protected]"
    
  39.         )
    
  40.         cls.r2.save()
    
  41.         # Create an Article.
    
  42.         cls.a = Article(
    
  43.             headline="This is a test",
    
  44.             pub_date=datetime.date(2005, 7, 27),
    
  45.             reporter=cls.r,
    
  46.         )
    
  47.         cls.a.save()
    
  48. 
    
  49.     def test_get(self):
    
  50.         # Article objects have access to their related Reporter objects.
    
  51.         r = self.a.reporter
    
  52.         self.assertEqual(r.id, self.r.id)
    
  53.         self.assertEqual((r.first_name, self.r.last_name), ("John", "Smith"))
    
  54. 
    
  55.     def test_create(self):
    
  56.         # You can also instantiate an Article by passing the Reporter's ID
    
  57.         # instead of a Reporter object.
    
  58.         a3 = Article(
    
  59.             headline="Third article",
    
  60.             pub_date=datetime.date(2005, 7, 27),
    
  61.             reporter_id=self.r.id,
    
  62.         )
    
  63.         a3.save()
    
  64.         self.assertEqual(a3.reporter.id, self.r.id)
    
  65. 
    
  66.         # Similarly, the reporter ID can be a string.
    
  67.         a4 = Article(
    
  68.             headline="Fourth article",
    
  69.             pub_date=datetime.date(2005, 7, 27),
    
  70.             reporter_id=str(self.r.id),
    
  71.         )
    
  72.         a4.save()
    
  73.         self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>")
    
  74. 
    
  75.     def test_add(self):
    
  76.         # Create an Article via the Reporter object.
    
  77.         new_article = self.r.article_set.create(
    
  78.             headline="John's second story", pub_date=datetime.date(2005, 7, 29)
    
  79.         )
    
  80.         self.assertEqual(repr(new_article), "<Article: John's second story>")
    
  81.         self.assertEqual(new_article.reporter.id, self.r.id)
    
  82. 
    
  83.         # Create a new article, and add it to the article set.
    
  84.         new_article2 = Article(
    
  85.             headline="Paul's story", pub_date=datetime.date(2006, 1, 17)
    
  86.         )
    
  87.         msg = (
    
  88.             "<Article: Paul's story> instance isn't saved. Use bulk=False or save the "
    
  89.             "object first."
    
  90.         )
    
  91.         with self.assertRaisesMessage(ValueError, msg):
    
  92.             self.r.article_set.add(new_article2)
    
  93. 
    
  94.         self.r.article_set.add(new_article2, bulk=False)
    
  95.         self.assertEqual(new_article2.reporter.id, self.r.id)
    
  96.         self.assertSequenceEqual(
    
  97.             self.r.article_set.all(),
    
  98.             [new_article, new_article2, self.a],
    
  99.         )
    
  100. 
    
  101.         # Add the same article to a different article set - check that it moves.
    
  102.         self.r2.article_set.add(new_article2)
    
  103.         self.assertEqual(new_article2.reporter.id, self.r2.id)
    
  104.         self.assertSequenceEqual(self.r2.article_set.all(), [new_article2])
    
  105. 
    
  106.         # Adding an object of the wrong type raises TypeError.
    
  107.         with transaction.atomic():
    
  108.             with self.assertRaisesMessage(
    
  109.                 TypeError, "'Article' instance expected, got <Reporter:"
    
  110.             ):
    
  111.                 self.r.article_set.add(self.r2)
    
  112.         self.assertSequenceEqual(
    
  113.             self.r.article_set.all(),
    
  114.             [new_article, self.a],
    
  115.         )
    
  116. 
    
  117.     def test_set(self):
    
  118.         new_article = self.r.article_set.create(
    
  119.             headline="John's second story", pub_date=datetime.date(2005, 7, 29)
    
  120.         )
    
  121.         new_article2 = self.r2.article_set.create(
    
  122.             headline="Paul's story", pub_date=datetime.date(2006, 1, 17)
    
  123.         )
    
  124. 
    
  125.         # Assign the article to the reporter.
    
  126.         new_article2.reporter = self.r
    
  127.         new_article2.save()
    
  128.         self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
    
  129.         self.assertEqual(new_article2.reporter.id, self.r.id)
    
  130.         self.assertSequenceEqual(
    
  131.             self.r.article_set.all(),
    
  132.             [new_article, new_article2, self.a],
    
  133.         )
    
  134.         self.assertSequenceEqual(self.r2.article_set.all(), [])
    
  135. 
    
  136.         # Set the article back again.
    
  137.         self.r2.article_set.set([new_article, new_article2])
    
  138.         self.assertSequenceEqual(self.r.article_set.all(), [self.a])
    
  139.         self.assertSequenceEqual(
    
  140.             self.r2.article_set.all(),
    
  141.             [new_article, new_article2],
    
  142.         )
    
  143. 
    
  144.         # Funny case - because the ForeignKey cannot be null,
    
  145.         # existing members of the set must remain.
    
  146.         self.r.article_set.set([new_article])
    
  147.         self.assertSequenceEqual(
    
  148.             self.r.article_set.all(),
    
  149.             [new_article, self.a],
    
  150.         )
    
  151.         self.assertSequenceEqual(self.r2.article_set.all(), [new_article2])
    
  152. 
    
  153.     def test_reverse_assignment_deprecation(self):
    
  154.         msg = (
    
  155.             "Direct assignment to the reverse side of a related set is "
    
  156.             "prohibited. Use article_set.set() instead."
    
  157.         )
    
  158.         with self.assertRaisesMessage(TypeError, msg):
    
  159.             self.r2.article_set = []
    
  160. 
    
  161.     def test_assign(self):
    
  162.         new_article = self.r.article_set.create(
    
  163.             headline="John's second story", pub_date=datetime.date(2005, 7, 29)
    
  164.         )
    
  165.         new_article2 = self.r2.article_set.create(
    
  166.             headline="Paul's story", pub_date=datetime.date(2006, 1, 17)
    
  167.         )
    
  168. 
    
  169.         # Assign the article to the reporter directly using the descriptor.
    
  170.         new_article2.reporter = self.r
    
  171.         new_article2.save()
    
  172.         self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
    
  173.         self.assertEqual(new_article2.reporter.id, self.r.id)
    
  174.         self.assertSequenceEqual(
    
  175.             self.r.article_set.all(),
    
  176.             [new_article, new_article2, self.a],
    
  177.         )
    
  178.         self.assertSequenceEqual(self.r2.article_set.all(), [])
    
  179. 
    
  180.         # Set the article back again using set() method.
    
  181.         self.r2.article_set.set([new_article, new_article2])
    
  182.         self.assertSequenceEqual(self.r.article_set.all(), [self.a])
    
  183.         self.assertSequenceEqual(
    
  184.             self.r2.article_set.all(),
    
  185.             [new_article, new_article2],
    
  186.         )
    
  187. 
    
  188.         # Because the ForeignKey cannot be null, existing members of the set
    
  189.         # must remain.
    
  190.         self.r.article_set.set([new_article])
    
  191.         self.assertSequenceEqual(
    
  192.             self.r.article_set.all(),
    
  193.             [new_article, self.a],
    
  194.         )
    
  195.         self.assertSequenceEqual(self.r2.article_set.all(), [new_article2])
    
  196.         # Reporter cannot be null - there should not be a clear or remove method
    
  197.         self.assertFalse(hasattr(self.r2.article_set, "remove"))
    
  198.         self.assertFalse(hasattr(self.r2.article_set, "clear"))
    
  199. 
    
  200.     def test_assign_fk_id_value(self):
    
  201.         parent = Parent.objects.create(name="jeff")
    
  202.         child1 = Child.objects.create(name="frank", parent=parent)
    
  203.         child2 = Child.objects.create(name="randy", parent=parent)
    
  204.         parent.bestchild = child1
    
  205.         parent.save()
    
  206.         parent.bestchild_id = child2.pk
    
  207.         parent.save()
    
  208.         self.assertEqual(parent.bestchild_id, child2.pk)
    
  209.         self.assertFalse(Parent.bestchild.is_cached(parent))
    
  210.         self.assertEqual(parent.bestchild, child2)
    
  211.         self.assertTrue(Parent.bestchild.is_cached(parent))
    
  212.         # Reassigning the same value doesn't clear cached instance.
    
  213.         parent.bestchild_id = child2.pk
    
  214.         self.assertTrue(Parent.bestchild.is_cached(parent))
    
  215. 
    
  216.     def test_assign_fk_id_none(self):
    
  217.         parent = Parent.objects.create(name="jeff")
    
  218.         child = Child.objects.create(name="frank", parent=parent)
    
  219.         parent.bestchild = child
    
  220.         parent.save()
    
  221.         parent.bestchild_id = None
    
  222.         parent.save()
    
  223.         self.assertIsNone(parent.bestchild_id)
    
  224.         self.assertFalse(Parent.bestchild.is_cached(parent))
    
  225.         self.assertIsNone(parent.bestchild)
    
  226.         self.assertTrue(Parent.bestchild.is_cached(parent))
    
  227. 
    
  228.     def test_selects(self):
    
  229.         new_article1 = self.r.article_set.create(
    
  230.             headline="John's second story",
    
  231.             pub_date=datetime.date(2005, 7, 29),
    
  232.         )
    
  233.         new_article2 = self.r2.article_set.create(
    
  234.             headline="Paul's story",
    
  235.             pub_date=datetime.date(2006, 1, 17),
    
  236.         )
    
  237.         # Reporter objects have access to their related Article objects.
    
  238.         self.assertSequenceEqual(
    
  239.             self.r.article_set.all(),
    
  240.             [new_article1, self.a],
    
  241.         )
    
  242.         self.assertSequenceEqual(
    
  243.             self.r.article_set.filter(headline__startswith="This"), [self.a]
    
  244.         )
    
  245.         self.assertEqual(self.r.article_set.count(), 2)
    
  246.         self.assertEqual(self.r2.article_set.count(), 1)
    
  247.         # Get articles by id
    
  248.         self.assertSequenceEqual(Article.objects.filter(id__exact=self.a.id), [self.a])
    
  249.         self.assertSequenceEqual(Article.objects.filter(pk=self.a.id), [self.a])
    
  250.         # Query on an article property
    
  251.         self.assertSequenceEqual(
    
  252.             Article.objects.filter(headline__startswith="This"), [self.a]
    
  253.         )
    
  254.         # The API automatically follows relationships as far as you need.
    
  255.         # Use double underscores to separate relationships.
    
  256.         # This works as many levels deep as you want. There's no limit.
    
  257.         # Find all Articles for any Reporter whose first name is "John".
    
  258.         self.assertSequenceEqual(
    
  259.             Article.objects.filter(reporter__first_name__exact="John"),
    
  260.             [new_article1, self.a],
    
  261.         )
    
  262.         # Implied __exact also works
    
  263.         self.assertSequenceEqual(
    
  264.             Article.objects.filter(reporter__first_name="John"),
    
  265.             [new_article1, self.a],
    
  266.         )
    
  267.         # Query twice over the related field.
    
  268.         self.assertSequenceEqual(
    
  269.             Article.objects.filter(
    
  270.                 reporter__first_name__exact="John", reporter__last_name__exact="Smith"
    
  271.             ),
    
  272.             [new_article1, self.a],
    
  273.         )
    
  274.         # The underlying query only makes one join when a related table is
    
  275.         # referenced twice.
    
  276.         queryset = Article.objects.filter(
    
  277.             reporter__first_name__exact="John", reporter__last_name__exact="Smith"
    
  278.         )
    
  279.         self.assertNumQueries(1, list, queryset)
    
  280.         self.assertEqual(
    
  281.             queryset.query.get_compiler(queryset.db).as_sql()[0].count("INNER JOIN"), 1
    
  282.         )
    
  283. 
    
  284.         # The automatically joined table has a predictable name.
    
  285.         self.assertSequenceEqual(
    
  286.             Article.objects.filter(reporter__first_name__exact="John").extra(
    
  287.                 where=["many_to_one_reporter.last_name='Smith'"]
    
  288.             ),
    
  289.             [new_article1, self.a],
    
  290.         )
    
  291.         # ... and should work fine with the string that comes out of
    
  292.         # forms.Form.cleaned_data.
    
  293.         self.assertQuerysetEqual(
    
  294.             (
    
  295.                 Article.objects.filter(reporter__first_name__exact="John").extra(
    
  296.                     where=["many_to_one_reporter.last_name='%s'" % "Smith"]
    
  297.                 )
    
  298.             ),
    
  299.             [new_article1, self.a],
    
  300.         )
    
  301.         # Find all Articles for a Reporter.
    
  302.         # Use direct ID check, pk check, and object comparison
    
  303.         self.assertSequenceEqual(
    
  304.             Article.objects.filter(reporter__id__exact=self.r.id),
    
  305.             [new_article1, self.a],
    
  306.         )
    
  307.         self.assertSequenceEqual(
    
  308.             Article.objects.filter(reporter__pk=self.r.id),
    
  309.             [new_article1, self.a],
    
  310.         )
    
  311.         self.assertSequenceEqual(
    
  312.             Article.objects.filter(reporter=self.r.id),
    
  313.             [new_article1, self.a],
    
  314.         )
    
  315.         self.assertSequenceEqual(
    
  316.             Article.objects.filter(reporter=self.r),
    
  317.             [new_article1, self.a],
    
  318.         )
    
  319.         self.assertSequenceEqual(
    
  320.             Article.objects.filter(reporter__in=[self.r.id, self.r2.id]).distinct(),
    
  321.             [new_article1, new_article2, self.a],
    
  322.         )
    
  323.         self.assertSequenceEqual(
    
  324.             Article.objects.filter(reporter__in=[self.r, self.r2]).distinct(),
    
  325.             [new_article1, new_article2, self.a],
    
  326.         )
    
  327.         # You can also use a queryset instead of a literal list of instances.
    
  328.         # The queryset must be reduced to a list of values using values(),
    
  329.         # then converted into a query
    
  330.         self.assertSequenceEqual(
    
  331.             Article.objects.filter(
    
  332.                 reporter__in=Reporter.objects.filter(first_name="John")
    
  333.                 .values("pk")
    
  334.                 .query
    
  335.             ).distinct(),
    
  336.             [new_article1, self.a],
    
  337.         )
    
  338. 
    
  339.     def test_reverse_selects(self):
    
  340.         a3 = Article.objects.create(
    
  341.             headline="Third article",
    
  342.             pub_date=datetime.date(2005, 7, 27),
    
  343.             reporter_id=self.r.id,
    
  344.         )
    
  345.         Article.objects.create(
    
  346.             headline="Fourth article",
    
  347.             pub_date=datetime.date(2005, 7, 27),
    
  348.             reporter_id=self.r.id,
    
  349.         )
    
  350.         john_smith = [self.r]
    
  351.         # Reporters can be queried
    
  352.         self.assertSequenceEqual(
    
  353.             Reporter.objects.filter(id__exact=self.r.id), john_smith
    
  354.         )
    
  355.         self.assertSequenceEqual(Reporter.objects.filter(pk=self.r.id), john_smith)
    
  356.         self.assertSequenceEqual(
    
  357.             Reporter.objects.filter(first_name__startswith="John"), john_smith
    
  358.         )
    
  359.         # Reporters can query in opposite direction of ForeignKey definition
    
  360.         self.assertSequenceEqual(
    
  361.             Reporter.objects.filter(article__id__exact=self.a.id), john_smith
    
  362.         )
    
  363.         self.assertSequenceEqual(
    
  364.             Reporter.objects.filter(article__pk=self.a.id), john_smith
    
  365.         )
    
  366.         self.assertSequenceEqual(Reporter.objects.filter(article=self.a.id), john_smith)
    
  367.         self.assertSequenceEqual(Reporter.objects.filter(article=self.a), john_smith)
    
  368.         self.assertSequenceEqual(
    
  369.             Reporter.objects.filter(article__in=[self.a.id, a3.id]).distinct(),
    
  370.             john_smith,
    
  371.         )
    
  372.         self.assertSequenceEqual(
    
  373.             Reporter.objects.filter(article__in=[self.a.id, a3]).distinct(), john_smith
    
  374.         )
    
  375.         self.assertSequenceEqual(
    
  376.             Reporter.objects.filter(article__in=[self.a, a3]).distinct(), john_smith
    
  377.         )
    
  378.         self.assertCountEqual(
    
  379.             Reporter.objects.filter(article__headline__startswith="T"),
    
  380.             [self.r, self.r],
    
  381.         )
    
  382.         self.assertSequenceEqual(
    
  383.             Reporter.objects.filter(article__headline__startswith="T").distinct(),
    
  384.             john_smith,
    
  385.         )
    
  386. 
    
  387.         # Counting in the opposite direction works in conjunction with distinct()
    
  388.         self.assertEqual(
    
  389.             Reporter.objects.filter(article__headline__startswith="T").count(), 2
    
  390.         )
    
  391.         self.assertEqual(
    
  392.             Reporter.objects.filter(article__headline__startswith="T")
    
  393.             .distinct()
    
  394.             .count(),
    
  395.             1,
    
  396.         )
    
  397. 
    
  398.         # Queries can go round in circles.
    
  399.         self.assertCountEqual(
    
  400.             Reporter.objects.filter(article__reporter__first_name__startswith="John"),
    
  401.             [self.r, self.r, self.r],
    
  402.         )
    
  403.         self.assertSequenceEqual(
    
  404.             Reporter.objects.filter(
    
  405.                 article__reporter__first_name__startswith="John"
    
  406.             ).distinct(),
    
  407.             john_smith,
    
  408.         )
    
  409.         self.assertSequenceEqual(
    
  410.             Reporter.objects.filter(article__reporter__exact=self.r).distinct(),
    
  411.             john_smith,
    
  412.         )
    
  413. 
    
  414.         # Implied __exact also works.
    
  415.         self.assertSequenceEqual(
    
  416.             Reporter.objects.filter(article__reporter=self.r).distinct(), john_smith
    
  417.         )
    
  418. 
    
  419.         # It's possible to use values() calls across many-to-one relations.
    
  420.         # (Note, too, that we clear the ordering here so as not to drag the
    
  421.         # 'headline' field into the columns being used to determine uniqueness)
    
  422.         d = {"reporter__first_name": "John", "reporter__last_name": "Smith"}
    
  423.         qs = (
    
  424.             Article.objects.filter(
    
  425.                 reporter=self.r,
    
  426.             )
    
  427.             .distinct()
    
  428.             .order_by()
    
  429.             .values("reporter__first_name", "reporter__last_name")
    
  430.         )
    
  431.         self.assertEqual([d], list(qs))
    
  432. 
    
  433.     def test_select_related(self):
    
  434.         # Article.objects.select_related().dates() works properly when there
    
  435.         # are multiple Articles with the same date but different foreign-key
    
  436.         # objects (Reporters).
    
  437.         r1 = Reporter.objects.create(
    
  438.             first_name="Mike", last_name="Royko", email="[email protected]"
    
  439.         )
    
  440.         r2 = Reporter.objects.create(
    
  441.             first_name="John", last_name="Kass", email="[email protected]"
    
  442.         )
    
  443.         Article.objects.create(
    
  444.             headline="First", pub_date=datetime.date(1980, 4, 23), reporter=r1
    
  445.         )
    
  446.         Article.objects.create(
    
  447.             headline="Second", pub_date=datetime.date(1980, 4, 23), reporter=r2
    
  448.         )
    
  449.         self.assertEqual(
    
  450.             list(Article.objects.select_related().dates("pub_date", "day")),
    
  451.             [datetime.date(1980, 4, 23), datetime.date(2005, 7, 27)],
    
  452.         )
    
  453.         self.assertEqual(
    
  454.             list(Article.objects.select_related().dates("pub_date", "month")),
    
  455.             [datetime.date(1980, 4, 1), datetime.date(2005, 7, 1)],
    
  456.         )
    
  457.         self.assertEqual(
    
  458.             list(Article.objects.select_related().dates("pub_date", "year")),
    
  459.             [datetime.date(1980, 1, 1), datetime.date(2005, 1, 1)],
    
  460.         )
    
  461. 
    
  462.     def test_delete(self):
    
  463.         new_article1 = self.r.article_set.create(
    
  464.             headline="John's second story",
    
  465.             pub_date=datetime.date(2005, 7, 29),
    
  466.         )
    
  467.         new_article2 = self.r2.article_set.create(
    
  468.             headline="Paul's story",
    
  469.             pub_date=datetime.date(2006, 1, 17),
    
  470.         )
    
  471.         new_article3 = Article.objects.create(
    
  472.             headline="Third article",
    
  473.             pub_date=datetime.date(2005, 7, 27),
    
  474.             reporter_id=self.r.id,
    
  475.         )
    
  476.         new_article4 = Article.objects.create(
    
  477.             headline="Fourth article",
    
  478.             pub_date=datetime.date(2005, 7, 27),
    
  479.             reporter_id=str(self.r.id),
    
  480.         )
    
  481.         # If you delete a reporter, their articles will be deleted.
    
  482.         self.assertSequenceEqual(
    
  483.             Article.objects.all(),
    
  484.             [new_article4, new_article1, new_article2, new_article3, self.a],
    
  485.         )
    
  486.         self.assertSequenceEqual(
    
  487.             Reporter.objects.order_by("first_name"),
    
  488.             [self.r, self.r2],
    
  489.         )
    
  490.         self.r2.delete()
    
  491.         self.assertSequenceEqual(
    
  492.             Article.objects.all(),
    
  493.             [new_article4, new_article1, new_article3, self.a],
    
  494.         )
    
  495.         self.assertSequenceEqual(Reporter.objects.order_by("first_name"), [self.r])
    
  496.         # You can delete using a JOIN in the query.
    
  497.         Reporter.objects.filter(article__headline__startswith="This").delete()
    
  498.         self.assertSequenceEqual(Reporter.objects.all(), [])
    
  499.         self.assertSequenceEqual(Article.objects.all(), [])
    
  500. 
    
  501.     def test_explicit_fk(self):
    
  502.         # Create a new Article with get_or_create using an explicit value
    
  503.         # for a ForeignKey.
    
  504.         a2, created = Article.objects.get_or_create(
    
  505.             headline="John's second test",
    
  506.             pub_date=datetime.date(2011, 5, 7),
    
  507.             reporter_id=self.r.id,
    
  508.         )
    
  509.         self.assertTrue(created)
    
  510.         self.assertEqual(a2.reporter.id, self.r.id)
    
  511. 
    
  512.         # You can specify filters containing the explicit FK value.
    
  513.         self.assertSequenceEqual(
    
  514.             Article.objects.filter(reporter_id__exact=self.r.id),
    
  515.             [a2, self.a],
    
  516.         )
    
  517. 
    
  518.         # Create an Article by Paul for the same date.
    
  519.         a3 = Article.objects.create(
    
  520.             headline="Paul's commentary",
    
  521.             pub_date=datetime.date(2011, 5, 7),
    
  522.             reporter_id=self.r2.id,
    
  523.         )
    
  524.         self.assertEqual(a3.reporter.id, self.r2.id)
    
  525. 
    
  526.         # Get should respect explicit foreign keys as well.
    
  527.         msg = "get() returned more than one Article -- it returned 2!"
    
  528.         with self.assertRaisesMessage(MultipleObjectsReturned, msg):
    
  529.             Article.objects.get(reporter_id=self.r.id)
    
  530.         self.assertEqual(
    
  531.             repr(a3),
    
  532.             repr(
    
  533.                 Article.objects.get(
    
  534.                     reporter_id=self.r2.id, pub_date=datetime.date(2011, 5, 7)
    
  535.                 )
    
  536.             ),
    
  537.         )
    
  538. 
    
  539.     def test_deepcopy_and_circular_references(self):
    
  540.         # Regression for #12876 -- Model methods that include queries that
    
  541.         # recursive don't cause recursion depth problems under deepcopy.
    
  542.         self.r.cached_query = Article.objects.filter(reporter=self.r)
    
  543.         self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
    
  544. 
    
  545.     def test_manager_class_caching(self):
    
  546.         r1 = Reporter.objects.create(first_name="Mike")
    
  547.         r2 = Reporter.objects.create(first_name="John")
    
  548. 
    
  549.         # Same twice
    
  550.         self.assertIs(r1.article_set.__class__, r1.article_set.__class__)
    
  551. 
    
  552.         # Same as each other
    
  553.         self.assertIs(r1.article_set.__class__, r2.article_set.__class__)
    
  554. 
    
  555.     def test_create_relation_with_gettext_lazy(self):
    
  556.         reporter = Reporter.objects.create(
    
  557.             first_name="John", last_name="Smith", email="[email protected]"
    
  558.         )
    
  559.         lazy = gettext_lazy("test")
    
  560.         reporter.article_set.create(headline=lazy, pub_date=datetime.date(2011, 6, 10))
    
  561.         notlazy = str(lazy)
    
  562.         article = reporter.article_set.get()
    
  563.         self.assertEqual(article.headline, notlazy)
    
  564. 
    
  565.     def test_values_list_exception(self):
    
  566.         expected_message = (
    
  567.             "Cannot resolve keyword 'notafield' into field. Choices are: %s"
    
  568.         )
    
  569.         reporter_fields = ", ".join(sorted(f.name for f in Reporter._meta.get_fields()))
    
  570.         with self.assertRaisesMessage(FieldError, expected_message % reporter_fields):
    
  571.             Article.objects.values_list("reporter__notafield")
    
  572.         article_fields = ", ".join(
    
  573.             ["EXTRA"] + sorted(f.name for f in Article._meta.get_fields())
    
  574.         )
    
  575.         with self.assertRaisesMessage(FieldError, expected_message % article_fields):
    
  576.             Article.objects.extra(select={"EXTRA": "EXTRA_SELECT"}).values_list(
    
  577.                 "notafield"
    
  578.             )
    
  579. 
    
  580.     def test_fk_assignment_and_related_object_cache(self):
    
  581.         # Tests of ForeignKey assignment and the related-object cache (see #6886).
    
  582. 
    
  583.         p = Parent.objects.create(name="Parent")
    
  584.         c = Child.objects.create(name="Child", parent=p)
    
  585. 
    
  586.         # Look up the object again so that we get a "fresh" object.
    
  587.         c = Child.objects.get(name="Child")
    
  588.         p = c.parent
    
  589. 
    
  590.         # Accessing the related object again returns the exactly same object.
    
  591.         self.assertIs(c.parent, p)
    
  592. 
    
  593.         # But if we kill the cache, we get a new object.
    
  594.         del c._state.fields_cache["parent"]
    
  595.         self.assertIsNot(c.parent, p)
    
  596. 
    
  597.         # Assigning a new object results in that object getting cached immediately.
    
  598.         p2 = Parent.objects.create(name="Parent 2")
    
  599.         c.parent = p2
    
  600.         self.assertIs(c.parent, p2)
    
  601. 
    
  602.         # Assigning None succeeds if field is null=True.
    
  603.         p.bestchild = None
    
  604.         self.assertIsNone(p.bestchild)
    
  605. 
    
  606.         # bestchild should still be None after saving.
    
  607.         p.save()
    
  608.         self.assertIsNone(p.bestchild)
    
  609. 
    
  610.         # bestchild should still be None after fetching the object again.
    
  611.         p = Parent.objects.get(name="Parent")
    
  612.         self.assertIsNone(p.bestchild)
    
  613. 
    
  614.         # Assigning None will not fail: Child.parent is null=False.
    
  615.         setattr(c, "parent", None)
    
  616. 
    
  617.         # You also can't assign an object of the wrong type here
    
  618.         msg = (
    
  619.             'Cannot assign "<First: First object (1)>": "Child.parent" must '
    
  620.             'be a "Parent" instance.'
    
  621.         )
    
  622.         with self.assertRaisesMessage(ValueError, msg):
    
  623.             setattr(c, "parent", First(id=1, second=1))
    
  624. 
    
  625.         # You can assign None to Child.parent during object creation.
    
  626.         Child(name="xyzzy", parent=None)
    
  627. 
    
  628.         # But when trying to save a Child with parent=None, the database will
    
  629.         # raise IntegrityError.
    
  630.         with self.assertRaises(IntegrityError), transaction.atomic():
    
  631.             Child.objects.create(name="xyzzy", parent=None)
    
  632. 
    
  633.         # Creation using keyword argument should cache the related object.
    
  634.         p = Parent.objects.get(name="Parent")
    
  635.         c = Child(parent=p)
    
  636.         self.assertIs(c.parent, p)
    
  637. 
    
  638.         # Creation using keyword argument and unsaved related instance (#8070).
    
  639.         p = Parent()
    
  640.         msg = (
    
  641.             "save() prohibited to prevent data loss due to unsaved related object "
    
  642.             "'parent'."
    
  643.         )
    
  644.         with self.assertRaisesMessage(ValueError, msg):
    
  645.             Child.objects.create(parent=p)
    
  646. 
    
  647.         with self.assertRaisesMessage(ValueError, msg):
    
  648.             ToFieldChild.objects.create(parent=p)
    
  649. 
    
  650.         # Creation using attname keyword argument and an id will cause the
    
  651.         # related object to be fetched.
    
  652.         p = Parent.objects.get(name="Parent")
    
  653.         c = Child(parent_id=p.id)
    
  654.         self.assertIsNot(c.parent, p)
    
  655.         self.assertEqual(c.parent, p)
    
  656. 
    
  657.     def test_save_nullable_fk_after_parent(self):
    
  658.         parent = Parent()
    
  659.         child = ChildNullableParent(parent=parent)
    
  660.         parent.save()
    
  661.         child.save()
    
  662.         child.refresh_from_db()
    
  663.         self.assertEqual(child.parent, parent)
    
  664. 
    
  665.     def test_save_nullable_fk_after_parent_with_to_field(self):
    
  666.         parent = Parent(name="jeff")
    
  667.         child = ToFieldChild(parent=parent)
    
  668.         parent.save()
    
  669.         child.save()
    
  670.         child.refresh_from_db()
    
  671.         self.assertEqual(child.parent, parent)
    
  672.         self.assertEqual(child.parent_id, parent.name)
    
  673. 
    
  674.     def test_save_fk_after_parent_with_non_numeric_pk_set_on_child(self):
    
  675.         parent = ParentStringPrimaryKey()
    
  676.         child = ChildStringPrimaryKeyParent(parent=parent)
    
  677.         child.parent.name = "jeff"
    
  678.         parent.save()
    
  679.         child.save()
    
  680.         child.refresh_from_db()
    
  681.         self.assertEqual(child.parent, parent)
    
  682.         self.assertEqual(child.parent_id, parent.name)
    
  683. 
    
  684.     def test_fk_to_bigautofield(self):
    
  685.         ch = City.objects.create(name="Chicago")
    
  686.         District.objects.create(city=ch, name="Far South")
    
  687.         District.objects.create(city=ch, name="North")
    
  688. 
    
  689.         ny = City.objects.create(name="New York", id=2**33)
    
  690.         District.objects.create(city=ny, name="Brooklyn")
    
  691.         District.objects.create(city=ny, name="Manhattan")
    
  692. 
    
  693.     def test_fk_to_smallautofield(self):
    
  694.         us = Country.objects.create(name="United States")
    
  695.         City.objects.create(country=us, name="Chicago")
    
  696.         City.objects.create(country=us, name="New York")
    
  697. 
    
  698.         uk = Country.objects.create(name="United Kingdom", id=2**11)
    
  699.         City.objects.create(country=uk, name="London")
    
  700.         City.objects.create(country=uk, name="Edinburgh")
    
  701. 
    
  702.     def test_multiple_foreignkeys(self):
    
  703.         # Test of multiple ForeignKeys to the same model (bug #7125).
    
  704.         c1 = Category.objects.create(name="First")
    
  705.         c2 = Category.objects.create(name="Second")
    
  706.         c3 = Category.objects.create(name="Third")
    
  707.         r1 = Record.objects.create(category=c1)
    
  708.         r2 = Record.objects.create(category=c1)
    
  709.         r3 = Record.objects.create(category=c2)
    
  710.         r4 = Record.objects.create(category=c2)
    
  711.         r5 = Record.objects.create(category=c3)
    
  712.         Relation.objects.create(left=r1, right=r2)
    
  713.         Relation.objects.create(left=r3, right=r4)
    
  714.         rel = Relation.objects.create(left=r1, right=r3)
    
  715.         Relation.objects.create(left=r5, right=r2)
    
  716.         Relation.objects.create(left=r3, right=r2)
    
  717. 
    
  718.         q1 = Relation.objects.filter(
    
  719.             left__category__name__in=["First"], right__category__name__in=["Second"]
    
  720.         )
    
  721.         self.assertSequenceEqual(q1, [rel])
    
  722. 
    
  723.         q2 = Category.objects.filter(
    
  724.             record__left_set__right__category__name="Second"
    
  725.         ).order_by("name")
    
  726.         self.assertSequenceEqual(q2, [c1, c2])
    
  727. 
    
  728.         p = Parent.objects.create(name="Parent")
    
  729.         c = Child.objects.create(name="Child", parent=p)
    
  730.         msg = 'Cannot assign "%r": "Child.parent" must be a "Parent" instance.' % c
    
  731.         with self.assertRaisesMessage(ValueError, msg):
    
  732.             Child.objects.create(name="Grandchild", parent=c)
    
  733. 
    
  734.     def test_fk_instantiation_outside_model(self):
    
  735.         # Regression for #12190 -- Should be able to instantiate a FK outside
    
  736.         # of a model, and interrogate its related field.
    
  737.         cat = models.ForeignKey(Category, models.CASCADE)
    
  738.         self.assertEqual("id", cat.remote_field.get_related_field().name)
    
  739. 
    
  740.     def test_relation_unsaved(self):
    
  741.         Third.objects.create(name="Third 1")
    
  742.         Third.objects.create(name="Third 2")
    
  743.         th = Third(name="testing")
    
  744.         # The object isn't saved and the relation cannot be used.
    
  745.         msg = (
    
  746.             "'Third' instance needs to have a primary key value before this "
    
  747.             "relationship can be used."
    
  748.         )
    
  749.         with self.assertRaisesMessage(ValueError, msg):
    
  750.             th.child_set.count()
    
  751.         # The reverse foreign key manager can be created.
    
  752.         self.assertEqual(th.child_set.model, Third)
    
  753. 
    
  754.         th.save()
    
  755.         # Now the model is saved, so we will need to execute a query.
    
  756.         with self.assertNumQueries(1):
    
  757.             self.assertEqual(th.child_set.count(), 0)
    
  758. 
    
  759.     def test_related_object(self):
    
  760.         public_school = School.objects.create(is_public=True)
    
  761.         public_student = Student.objects.create(school=public_school)
    
  762. 
    
  763.         private_school = School.objects.create(is_public=False)
    
  764.         private_student = Student.objects.create(school=private_school)
    
  765. 
    
  766.         # Only one school is available via all() due to the custom default manager.
    
  767.         self.assertSequenceEqual(School.objects.all(), [public_school])
    
  768. 
    
  769.         self.assertEqual(public_student.school, public_school)
    
  770. 
    
  771.         # Make sure the base manager is used so that a student can still access
    
  772.         # its related school even if the default manager doesn't normally
    
  773.         # allow it.
    
  774.         self.assertEqual(private_student.school, private_school)
    
  775. 
    
  776.         School._meta.base_manager_name = "objects"
    
  777.         School._meta._expire_cache()
    
  778.         try:
    
  779.             private_student = Student.objects.get(pk=private_student.pk)
    
  780.             with self.assertRaises(School.DoesNotExist):
    
  781.                 private_student.school
    
  782.         finally:
    
  783.             School._meta.base_manager_name = None
    
  784.             School._meta._expire_cache()
    
  785. 
    
  786.     def test_hasattr_related_object(self):
    
  787.         # The exception raised on attribute access when a related object
    
  788.         # doesn't exist should be an instance of a subclass of `AttributeError`
    
  789.         # refs #21563
    
  790.         self.assertFalse(hasattr(Article(), "reporter"))
    
  791. 
    
  792.     def test_clear_after_prefetch(self):
    
  793.         c = City.objects.create(name="Musical City")
    
  794.         d = District.objects.create(name="Ladida", city=c)
    
  795.         city = City.objects.prefetch_related("districts").get(id=c.id)
    
  796.         self.assertSequenceEqual(city.districts.all(), [d])
    
  797.         city.districts.clear()
    
  798.         self.assertSequenceEqual(city.districts.all(), [])
    
  799. 
    
  800.     def test_remove_after_prefetch(self):
    
  801.         c = City.objects.create(name="Musical City")
    
  802.         d = District.objects.create(name="Ladida", city=c)
    
  803.         city = City.objects.prefetch_related("districts").get(id=c.id)
    
  804.         self.assertSequenceEqual(city.districts.all(), [d])
    
  805.         city.districts.remove(d)
    
  806.         self.assertSequenceEqual(city.districts.all(), [])
    
  807. 
    
  808.     def test_add_after_prefetch(self):
    
  809.         c = City.objects.create(name="Musical City")
    
  810.         District.objects.create(name="Ladida", city=c)
    
  811.         d2 = District.objects.create(name="Ladidu")
    
  812.         city = City.objects.prefetch_related("districts").get(id=c.id)
    
  813.         self.assertEqual(city.districts.count(), 1)
    
  814.         city.districts.add(d2)
    
  815.         self.assertEqual(city.districts.count(), 2)
    
  816. 
    
  817.     def test_set_after_prefetch(self):
    
  818.         c = City.objects.create(name="Musical City")
    
  819.         District.objects.create(name="Ladida", city=c)
    
  820.         d2 = District.objects.create(name="Ladidu")
    
  821.         city = City.objects.prefetch_related("districts").get(id=c.id)
    
  822.         self.assertEqual(city.districts.count(), 1)
    
  823.         city.districts.set([d2])
    
  824.         self.assertSequenceEqual(city.districts.all(), [d2])
    
  825. 
    
  826.     def test_add_then_remove_after_prefetch(self):
    
  827.         c = City.objects.create(name="Musical City")
    
  828.         District.objects.create(name="Ladida", city=c)
    
  829.         d2 = District.objects.create(name="Ladidu")
    
  830.         city = City.objects.prefetch_related("districts").get(id=c.id)
    
  831.         self.assertEqual(city.districts.count(), 1)
    
  832.         city.districts.add(d2)
    
  833.         self.assertEqual(city.districts.count(), 2)
    
  834.         city.districts.remove(d2)
    
  835.         self.assertEqual(city.districts.count(), 1)
    
  836. 
    
  837.     def test_cached_relation_invalidated_on_save(self):
    
  838.         """
    
  839.         Model.save() invalidates stale ForeignKey relations after a primary key
    
  840.         assignment.
    
  841.         """
    
  842.         self.assertEqual(self.a.reporter, self.r)  # caches a.reporter
    
  843.         self.a.reporter_id = self.r2.pk
    
  844.         self.a.save()
    
  845.         self.assertEqual(self.a.reporter, self.r2)
    
  846. 
    
  847.     def test_cached_foreign_key_with_to_field_not_cleared_by_save(self):
    
  848.         parent = Parent.objects.create(name="a")
    
  849.         child = ToFieldChild.objects.create(parent=parent)
    
  850.         with self.assertNumQueries(0):
    
  851.             self.assertIs(child.parent, parent)
    
  852. 
    
  853.     def test_reverse_foreign_key_instance_to_field_caching(self):
    
  854.         parent = Parent.objects.create(name="a")
    
  855.         ToFieldChild.objects.create(parent=parent)
    
  856.         child = parent.to_field_children.get()
    
  857.         with self.assertNumQueries(0):
    
  858.             self.assertIs(child.parent, parent)
    
  859. 
    
  860.     def test_add_remove_set_by_pk_raises(self):
    
  861.         usa = Country.objects.create(name="United States")
    
  862.         chicago = City.objects.create(name="Chicago")
    
  863.         msg = "'City' instance expected, got %s" % chicago.pk
    
  864.         with self.assertRaisesMessage(TypeError, msg):
    
  865.             usa.cities.add(chicago.pk)
    
  866.         with self.assertRaisesMessage(TypeError, msg):
    
  867.             usa.cities.remove(chicago.pk)
    
  868.         with self.assertRaisesMessage(TypeError, msg):
    
  869.             usa.cities.set([chicago.pk])