#29908: Blog access in b.entry_set.all()[i].blog should not hit the database
-------------------------------------+-------------------------------------
     Reporter:  Carsten Fuchs        |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  1.11
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Carsten Fuchs):

 Hi Tim,

 it seems that this is triggered when the ForeignKey's `to_field` parameter
 is used.
 The test fails with the following model `EntryB`:

 {{{
 #!python
 from django.db import models

 class Blog(models.Model):
     key = models.CharField(max_length=10, unique=True)
     name = models.CharField(max_length=100)

     def __str__(self):
         return self.name

 class EntryA(models.Model):
     blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
     headline = models.CharField(max_length=255)

 class EntryB(models.Model):
     blog = models.ForeignKey(Blog, on_delete=models.CASCADE,
 to_field='key')   # this triggers the problem
     headline = models.CharField(max_length=255)
 }}}

 Test cases:
 {{{
 #!python
 from django.test import TestCase
 from TestApp.models import Blog, EntryA, EntryB


 class TestBlogs(TestCase):

     def test_A(self):
         blog = Blog.objects.create(name='Beatles Blog')
         EntryA.objects.create(blog=blog)
         EntryA.objects.create(blog=blog)

         with self.assertNumQueries(1):    # succeeds
             for e in blog.entrya_set.all():
                 self.assertEqual(e.blog.name, 'Beatles Blog')

     def test_B(self):
         blog = Blog.objects.create(name='Beatles Blog')
         EntryB.objects.create(blog=blog)
         EntryB.objects.create(blog=blog)

         with self.assertNumQueries(1):    # This fails!
             for e in blog.entryb_set.all():
                 self.assertEqual(e.blog.name, 'Beatles Blog')
 }}}

 Test results:
 {{{
 $ ./manage.py test
 Creating test database for alias 'default'...
 System check identified no issues (0 silenced).
 .F
 ======================================================================
 FAIL: test_B (TestApp.tests.TestBlogs)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "/home/carsten/xxxTestProject/TestApp/tests.py", line 23, in test_B
     self.assertEqual(e.blog.name, 'Beatles Blog')
   File "/home/carsten/.virtualenvs/Zeiterfassung/lib/python3.6/site-
 packages/django/test/testcases.py", line 88, in __exit__
     query['sql'] for query in self.captured_queries
 AssertionError: 3 != 1 : 3 queries executed, 1 expected
 Captured queries were:
 SELECT "TestApp_entryb"."id", "TestApp_entryb"."blog_id",
 "TestApp_entryb"."headline" FROM "TestApp_entryb" WHERE
 "TestApp_entryb"."blog_id" = ''
 SELECT "TestApp_blog"."id", "TestApp_blog"."key", "TestApp_blog"."name"
 FROM "TestApp_blog" WHERE "TestApp_blog"."key" = ''
 SELECT "TestApp_blog"."id", "TestApp_blog"."key", "TestApp_blog"."name"
 FROM "TestApp_blog" WHERE "TestApp_blog"."key" = ''

 ----------------------------------------------------------------------
 Ran 2 tests in 0.003s

 FAILED (failures=1)
 Destroying test database for alias 'default'...
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29908#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.3408d257a378cbab164000348776d5ef%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to