Ticket #14146: 14146.diff

File 14146.diff, 5.0 KB (added by coleifer, 14 years ago)

Test case indicating failure

  • modeltests/model_inheritance/tests.py

     
     1from django.contrib.auth.models import User
     2from django.test import TestCase
     3
     4from modeltests.model_inheritance.models import (BasePost, PostSubclass,
     5    AuthorProfile, STATUS_GOOD, STATUS_BAD)
     6
     7class SubclassExclusionTestCase(TestCase):
     8    def setUp(self):
     9        # create some users!
     10        self.user_good = User.objects.create_user('good', 'good', 'good')
     11        self.user_neither = User.objects.create_user('neither', 'neither', 'neither')
     12        self.user_bad = User.objects.create_user('bad', 'bad', 'bad')
     13       
     14        # create profiles for good & bad users (but don't make one for neither
     15        self.profile_good = AuthorProfile.objects.create(user=self.user_good, status=STATUS_GOOD)
     16        self.profile_bad = AuthorProfile.objects.create(user=self.user_bad, status=STATUS_BAD)
     17       
     18        # create some posts for the users
     19        # note that i'm creating them in a different order - this is because the
     20        # inner query generates an incorrect join but can produce results that
     21        # "look" correct because of the primary keys being used.  this ensures
     22        # that the test will fail
     23        self.post_bad1 = PostSubclass.objects.create(author=self.user_bad, title='Bad post1')
     24        self.post_bad2 = PostSubclass.objects.create(author=self.user_bad, title='Bad post2')
     25        self.post_good1 = PostSubclass.objects.create(author=self.user_good, title='Good post1')
     26        self.post_good2 = PostSubclass.objects.create(author=self.user_good, title='Good post2')
     27        self.post_neither1 = PostSubclass.objects.create(author=self.user_neither, title='Neither post1')
     28        self.post_neither2 = PostSubclass.objects.create(author=self.user_neither, title='Neither post2')
     29   
     30    def test_filter_exclude(self):
     31        '''
     32        This is the query being generated by the .exclude() -- NOTE that lines
     33        44-47 are basically saying "Give me posts where the author id is NOT
     34        the base posts' id -- there's an extraneous join here that's messing
     35        the query up.
     36       
     37        SELECT "model_inheritance_basepost"."id", "model_inheritance_basepost"."author_id", "model_inheritance_basepost"."title", "model_inheritance_postsubclass"."basepost_ptr_id"
     38        FROM "model_inheritance_postsubclass"
     39
     40        INNER JOIN "model_inheritance_basepost"
     41            ON ("model_inheritance_postsubclass"."basepost_ptr_id" = "model_inheritance_basepost"."id")
     42
     43        WHERE NOT ((
     44            "model_inheritance_basepost"."author_id" IN (
     45           
     46                SELECT U1."id" FROM "model_inheritance_basepost" U1
     47                INNER JOIN "auth_user" U2
     48                    ON (U1."author_id" = U2."id")
     49                INNER JOIN "model_inheritance_authorprofile" U3
     50                    ON (U2."id" = U3."user_id")
     51                WHERE U3."status" = 2
     52            ) AND
     53            "model_inheritance_basepost"."author_id" IS NOT NULL
     54        ))
     55
     56        ORDER BY "model_inheritance_postsubclass"."basepost_ptr_id" ASC
     57        '''
     58        # ensure that querying across joins works fine
     59        good_post_qs = PostSubclass.objects.filter(
     60            author__authorprofile__status=STATUS_GOOD
     61        )
     62        self.assertEqual(list(good_post_qs), [self.post_good1, self.post_good2])
     63       
     64        # this works all fine and well, but say we want to get all posts where
     65        # the authors' status is anything *but* bad
     66        not_bad_post_qs = PostSubclass.objects.exclude(
     67            author__authorprofile__status=STATUS_BAD
     68        )
     69        self.assertEqual(list(not_bad_post_qs), [self.post_good1, self.post_good2, self.post_neither1, self.post_neither2])
  • modeltests/model_inheritance/models.py

     
    1212Both styles are demonstrated here.
    1313"""
    1414
     15from django.contrib.auth.models import User
    1516from django.db import models
    1617
    1718#
     
    144145    def __unicode__(self):
    145146        return self.content
    146147
     148
     149#
     150# Incorrect joins being generated on an inner query by the .exclude() method
     151#
     152
     153class BasePost(models.Model):
     154    author = models.ForeignKey(User, related_name='posts')
     155    title = models.CharField(max_length=100)
     156   
     157    class Meta:
     158        ordering = ['id']
     159
     160class PostSubclass(BasePost):
     161    pass
     162
     163STATUS_GOOD = 1
     164STATUS_BAD = 2
     165STATUS_CHOICES = (
     166    (STATUS_GOOD, 'Good'),
     167    (STATUS_BAD, 'Bad'),
     168)
     169class AuthorProfile(models.Model):
     170    user = models.OneToOneField(User)
     171    status = models.IntegerField(choices=STATUS_CHOICES)
     172
     173
    147174__test__ = {'API_TESTS':"""
    148175# The Student and Worker models both have 'name' and 'age' fields on them and
    149176# inherit the __unicode__() method, just as with normal Python subclassing.
Back to Top