Commit 3e713684 authored by Florian Hahn's avatar Florian Hahn Committed by Anssi Kääriäinen
Browse files

Fixed #10870 -- Added aggreation + generic reverse relation test

parent b4492a8c
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
# coding: utf-8
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@@ -22,6 +24,13 @@ class Publisher(models.Model):
        return self.name


class TaggedItem(models.Model):
    tag = models.CharField(max_length=100)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')


@python_2_unicode_compatible
class Book(models.Model):
    isbn = models.CharField(max_length=9)
@@ -33,6 +42,7 @@ class Book(models.Model):
    contact = models.ForeignKey(Author, related_name='book_contact_set')
    publisher = models.ForeignKey(Publisher)
    pubdate = models.DateField()
    tags = generic.GenericRelation(TaggedItem)

    class Meta:
        ordering = ('name',)
@@ -63,6 +73,14 @@ class Clues(models.Model):
    Clue = models.CharField(max_length=150)


class WithManualPK(models.Model):
    # The generic relations regression test needs two different model
    # classes with the same PK value, and there are some (external)
    # DB backends that don't work nicely when assigning integer to AutoField
    # column (MSSQL at least).
    id = models.IntegerField(primary_key=True)


@python_2_unicode_compatible
class HardbackBook(Book):
    weight = models.FloatField()
+39 −1
Original line number Diff line number Diff line
@@ -6,11 +6,13 @@ from decimal import Decimal
from operator import attrgetter

from django.core.exceptions import FieldError
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count, Max, Avg, Sum, StdDev, Variance, F, Q
from django.test import TestCase, Approximate, skipUnlessDBFeature
from django.utils import six

from .models import Author, Book, Publisher, Clues, Entries, HardbackBook
from .models import (Author, Book, Publisher, Clues, Entries, HardbackBook,
        TaggedItem, WithManualPK)


class AggregationTests(TestCase):
@@ -982,3 +984,39 @@ class AggregationTests(TestCase):
    def test_reverse_join_trimming(self):
        qs = Author.objects.annotate(Count('book_contact_set__contact'))
        self.assertIn(' JOIN ', str(qs.query))

    def test_aggregation_with_generic_reverse_relation(self):
        """
        Regression test for #10870:  Aggregates with joins ignore extra
        filters provided by setup_joins

        tests aggregations with generic reverse relations
        """
        b = Book.objects.get(name='Practical Django Projects')
        TaggedItem.objects.create(object_id=b.id, tag='intermediate',
                content_type=ContentType.objects.get_for_model(b))
        TaggedItem.objects.create(object_id=b.id, tag='django',
                content_type=ContentType.objects.get_for_model(b))
        # Assign a tag to model with same PK as the book above. If the JOIN
        # used in aggregation doesn't have content type as part of the
        # condition the annotation will also count the 'hi mom' tag for b.
        wmpk = WithManualPK.objects.create(id=b.pk)
        TaggedItem.objects.create(object_id=wmpk.id, tag='hi mom',
                content_type=ContentType.objects.get_for_model(wmpk))
        b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence')
        TaggedItem.objects.create(object_id=b.id, tag='intermediate',
                content_type=ContentType.objects.get_for_model(b))

        self.assertEqual(Book.objects.aggregate(Count('tags')), {'tags__count': 3})
        results = Book.objects.annotate(Count('tags')).order_by('-tags__count', 'name')
        self.assertEqual(
            [(b.name, b.tags__count) for b in results],
            [
                ('Practical Django Projects', 2),
                ('Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1),
                ('Artificial Intelligence: A Modern Approach', 0),
                ('Python Web Development with Django', 0),
                ('Sams Teach Yourself Django in 24 Hours', 0),
                ('The Definitive Guide to Django: Web Development Done Right', 0)
            ]
        )