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

This commit is contained in:
Florian Hahn 2013-02-13 18:37:40 +01:00 committed by Anssi Kääriäinen
parent b4492a8ca4
commit 3e71368423
2 changed files with 57 additions and 1 deletions

View File

@ -1,4 +1,6 @@
# 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()

View File

@ -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)
]
)