Loading AUTHORS +2 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,7 @@ answer newbie questions, and generally made Django that much better: Dmitri Fedortchenko <zeraien@gmail.com> Dmitry Jemerov <intelliyole@gmail.com> dne@mayonnaise.net Donald Harvey <donald@donaldharvey.co.uk> Donald Stufft <donald@stufft.io> Don Spaulding <donspauldingii@gmail.com> Doug Beck <doug@douglasbeck.com> Loading Loading @@ -710,6 +711,7 @@ answer newbie questions, and generally made Django that much better: Tyler Tarabula <tyler.tarabula@gmail.com> Tyson Tate <tyson@fallingbullets.com> Unai Zalakain <unai@gisa-elkartea.org> Valentina Mukhamedzhanova <umirra@gmail.com> valtron Vasiliy Stavenko <stavenko@gmail.com> Vasil Vangelovski Loading django/db/models/sql/compiler.py +4 −1 Original line number Diff line number Diff line Loading @@ -548,6 +548,9 @@ class SQLCompiler(object): _, targets, alias, joins, path, _ = self._setup_joins(parts, opts, None) targets, alias, _ = self.query.trim_joins(targets, joins, path) for target in targets: if name in self.query.annotation_select: result.append(name) else: result.append("%s.%s" % (qn(alias), qn2(target.column))) return result Loading django/db/models/sql/query.py +11 −2 Original line number Diff line number Diff line Loading @@ -1292,9 +1292,15 @@ class Query(object): cur_names_with_path = (name, []) if name == 'pk': name = opts.pk.name field = None try: field = opts.get_field(name) except FieldDoesNotExist: if name in self.annotation_select: field = self.annotation_select[name].output_field if field is not None: # Fields that contain one-to-many relations with a generic # model (like a GenericForeignKey) cannot generate reverse # relations and therefore cannot be used for reverse querying. Loading @@ -1305,8 +1311,11 @@ class Query(object): "querying. If it is a GenericForeignKey, consider " "adding a GenericRelation." % name ) try: model = field.model._meta.concrete_model except FieldDoesNotExist: except AttributeError: model = None else: # We didn't find the current field, so move position back # one step. pos -= 1 Loading docs/releases/1.9.txt +2 −0 Original line number Diff line number Diff line Loading @@ -462,6 +462,8 @@ Models :attr:`~django.db.models.SlugField.allow_unicode` argument to allow Unicode characters in slugs. * Added support for referencing annotations in ``QuerySet.distinct()``. CSRF ^^^^ Loading tests/annotations/tests.py +36 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ from django.db.models import ( F, BooleanField, CharField, Count, DateTimeField, ExpressionWrapper, Func, IntegerField, Sum, Value, ) from django.test import TestCase from django.db.models.functions import Lower from django.test import TestCase, skipUnlessDBFeature from django.utils import six from .models import ( Loading Loading @@ -160,6 +161,40 @@ class NonAggregateAnnotationTestCase(TestCase): other_agg = Author.objects.aggregate(age_sum=Sum('age')) self.assertEqual(agg['otherage_sum'], other_agg['age_sum']) @skipUnlessDBFeature('can_distinct_on_fields') def test_distinct_on_with_annotation(self): store = Store.objects.create( name='test store', original_opening=datetime.datetime.now(), friday_night_closing=datetime.time(21, 00, 00), ) names = [ 'Theodore Roosevelt', 'Eleanor Roosevelt', 'Franklin Roosevelt', 'Ned Stark', 'Catelyn Stark', ] for name in names: Employee.objects.create( store=store, first_name=name.split()[0], last_name=name.split()[1], age=30, salary=2000, ) people = Employee.objects.annotate( name_lower=Lower('last_name'), ).distinct('name_lower') self.assertEqual(set(p.last_name for p in people), {'Stark', 'Roosevelt'}) self.assertEqual(len(people), 2) people2 = Employee.objects.annotate( test_alias=F('store__name'), ).distinct('test_alias') self.assertEqual(len(people2), 1) def test_filter_annotation(self): books = Book.objects.annotate( is_book=Value(1, output_field=IntegerField()) Loading Loading
AUTHORS +2 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,7 @@ answer newbie questions, and generally made Django that much better: Dmitri Fedortchenko <zeraien@gmail.com> Dmitry Jemerov <intelliyole@gmail.com> dne@mayonnaise.net Donald Harvey <donald@donaldharvey.co.uk> Donald Stufft <donald@stufft.io> Don Spaulding <donspauldingii@gmail.com> Doug Beck <doug@douglasbeck.com> Loading Loading @@ -710,6 +711,7 @@ answer newbie questions, and generally made Django that much better: Tyler Tarabula <tyler.tarabula@gmail.com> Tyson Tate <tyson@fallingbullets.com> Unai Zalakain <unai@gisa-elkartea.org> Valentina Mukhamedzhanova <umirra@gmail.com> valtron Vasiliy Stavenko <stavenko@gmail.com> Vasil Vangelovski Loading
django/db/models/sql/compiler.py +4 −1 Original line number Diff line number Diff line Loading @@ -548,6 +548,9 @@ class SQLCompiler(object): _, targets, alias, joins, path, _ = self._setup_joins(parts, opts, None) targets, alias, _ = self.query.trim_joins(targets, joins, path) for target in targets: if name in self.query.annotation_select: result.append(name) else: result.append("%s.%s" % (qn(alias), qn2(target.column))) return result Loading
django/db/models/sql/query.py +11 −2 Original line number Diff line number Diff line Loading @@ -1292,9 +1292,15 @@ class Query(object): cur_names_with_path = (name, []) if name == 'pk': name = opts.pk.name field = None try: field = opts.get_field(name) except FieldDoesNotExist: if name in self.annotation_select: field = self.annotation_select[name].output_field if field is not None: # Fields that contain one-to-many relations with a generic # model (like a GenericForeignKey) cannot generate reverse # relations and therefore cannot be used for reverse querying. Loading @@ -1305,8 +1311,11 @@ class Query(object): "querying. If it is a GenericForeignKey, consider " "adding a GenericRelation." % name ) try: model = field.model._meta.concrete_model except FieldDoesNotExist: except AttributeError: model = None else: # We didn't find the current field, so move position back # one step. pos -= 1 Loading
docs/releases/1.9.txt +2 −0 Original line number Diff line number Diff line Loading @@ -462,6 +462,8 @@ Models :attr:`~django.db.models.SlugField.allow_unicode` argument to allow Unicode characters in slugs. * Added support for referencing annotations in ``QuerySet.distinct()``. CSRF ^^^^ Loading
tests/annotations/tests.py +36 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ from django.db.models import ( F, BooleanField, CharField, Count, DateTimeField, ExpressionWrapper, Func, IntegerField, Sum, Value, ) from django.test import TestCase from django.db.models.functions import Lower from django.test import TestCase, skipUnlessDBFeature from django.utils import six from .models import ( Loading Loading @@ -160,6 +161,40 @@ class NonAggregateAnnotationTestCase(TestCase): other_agg = Author.objects.aggregate(age_sum=Sum('age')) self.assertEqual(agg['otherage_sum'], other_agg['age_sum']) @skipUnlessDBFeature('can_distinct_on_fields') def test_distinct_on_with_annotation(self): store = Store.objects.create( name='test store', original_opening=datetime.datetime.now(), friday_night_closing=datetime.time(21, 00, 00), ) names = [ 'Theodore Roosevelt', 'Eleanor Roosevelt', 'Franklin Roosevelt', 'Ned Stark', 'Catelyn Stark', ] for name in names: Employee.objects.create( store=store, first_name=name.split()[0], last_name=name.split()[1], age=30, salary=2000, ) people = Employee.objects.annotate( name_lower=Lower('last_name'), ).distinct('name_lower') self.assertEqual(set(p.last_name for p in people), {'Stark', 'Roosevelt'}) self.assertEqual(len(people), 2) people2 = Employee.objects.annotate( test_alias=F('store__name'), ).distinct('test_alias') self.assertEqual(len(people2), 1) def test_filter_annotation(self): books = Book.objects.annotate( is_book=Value(1, output_field=IntegerField()) Loading