From 6c1b55d61a3b2c5e401bf63c1c65d569217a130b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 3 Nov 2013 01:52:40 -0700 Subject: Re-expose Count here --- django/contrib/gis/db/models/sql/aggregates.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'django') diff --git a/django/contrib/gis/db/models/sql/aggregates.py b/django/contrib/gis/db/models/sql/aggregates.py index f8f3ed1eb4..5a2e5d07be 100644 --- a/django/contrib/gis/db/models/sql/aggregates.py +++ b/django/contrib/gis/db/models/sql/aggregates.py @@ -1,7 +1,9 @@ -from django.db.models.sql.aggregates import Aggregate +from django.db.models.sql.aggregates import Aggregate, Count from django.contrib.gis.db.models.fields import GeometryField +__all__ = ['Count', 'Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] + class GeoAggregate(Aggregate): # Default SQL template for spatial aggregates. sql_template = '%(function)s(%(field)s)' -- cgit v1.3 From 4202d9cf0c359b5bb41247905454572b7f9644d9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 3 Nov 2013 01:53:28 -0700 Subject: Whitespace fix --- django/contrib/gis/db/models/sql/aggregates.py | 1 + 1 file changed, 1 insertion(+) (limited to 'django') diff --git a/django/contrib/gis/db/models/sql/aggregates.py b/django/contrib/gis/db/models/sql/aggregates.py index 5a2e5d07be..68fc12e54c 100644 --- a/django/contrib/gis/db/models/sql/aggregates.py +++ b/django/contrib/gis/db/models/sql/aggregates.py @@ -4,6 +4,7 @@ from django.contrib.gis.db.models.fields import GeometryField __all__ = ['Count', 'Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] + class GeoAggregate(Aggregate): # Default SQL template for spatial aggregates. sql_template = '%(function)s(%(field)s)' -- cgit v1.3 From 539e3693d4712b249a95cfad8cfdeecdad1777a6 Mon Sep 17 00:00:00 2001 From: Jim Bailey Date: Fri, 1 Nov 2013 12:55:35 +0000 Subject: Fixed #20849 -- ModelForms do not work well with prefetch_related. model_to_dict() (used when rendering forms) queries the database to get the list of primary keys for ManyToMany fields. This is unnecessary if the field queryset has been prefetched, all the keys are already in memory and can be obtained with a simple iteration. --- django/forms/models.py | 6 +++++- tests/model_forms/tests.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'django') diff --git a/django/forms/models.py b/django/forms/models.py index 71da43390c..32f0f043ae 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -134,7 +134,11 @@ def model_to_dict(instance, fields=None, exclude=None): data[f.name] = [] else: # MultipleChoiceWidget needs a list of pks, not object instances. - data[f.name] = list(f.value_from_object(instance).values_list('pk', flat=True)) + qs = f.value_from_object(instance) + if qs._result_cache is not None: + data[f.name] = [item.pk for item in qs] + else: + data[f.name] = list(qs.values_list('pk', flat=True)) else: data[f.name] = f.value_from_object(instance) return data diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index ddc7a4ceef..4b6c3b36ad 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -824,6 +824,41 @@ class ModelToDictTests(TestCase): # Ensure many-to-many relation appears as a list self.assertIsInstance(d['categories'], list) + def test_reuse_prefetched(self): + # model_to_dict should not hit the database if it can reuse + # the data populated by prefetch_related. + categories = [ + Category(name='TestName1', slug='TestName1', url='url1'), + Category(name='TestName2', slug='TestName2', url='url2'), + Category(name='TestName3', slug='TestName3', url='url3') + ] + for c in categories: + c.save() + writer = Writer(name='Test writer') + writer.save() + + art = Article( + headline='Test article', + slug='test-article', + pub_date=datetime.date(1988, 1, 4), + writer=writer, + article='Hello.' + ) + art.save() + for c in categories: + art.categories.add(c) + + art = Article.objects.prefetch_related('categories').get(pk=art.pk) + + with self.assertNumQueries(0): + d = model_to_dict(art) + + #Ensure all many-to-many categories appear in model_to_dict + for c in categories: + self.assertIn(c.pk, d['categories']) + #Ensure many-to-many relation appears as a list + self.assertIsInstance(d['categories'], list) + class OldFormForXTests(TestCase): def test_base_form(self): self.assertEqual(Category.objects.count(), 0) -- cgit v1.3 From f40f90d63b4be295269b5f0de5f919be22daba5c Mon Sep 17 00:00:00 2001 From: Florian Apolloner Date: Sun, 3 Nov 2013 12:45:15 +0100 Subject: Fixed regressions from 36ded01527b690b5df0574492af9cfcc2ea3d1dc. Refs #21302 --- django/contrib/gis/db/models/sql/aggregates.py | 5 +++-- django/db/models/sql/aggregates.py | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'django') diff --git a/django/contrib/gis/db/models/sql/aggregates.py b/django/contrib/gis/db/models/sql/aggregates.py index 68fc12e54c..c0a7d894eb 100644 --- a/django/contrib/gis/db/models/sql/aggregates.py +++ b/django/contrib/gis/db/models/sql/aggregates.py @@ -1,8 +1,9 @@ -from django.db.models.sql.aggregates import Aggregate, Count +from django.db.models.sql import aggregates +from django.db.models.sql.aggregates import * # NOQA from django.contrib.gis.db.models.fields import GeometryField -__all__ = ['Count', 'Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] +__all__ = ['Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] + aggregates.__all__ class GeoAggregate(Aggregate): diff --git a/django/db/models/sql/aggregates.py b/django/db/models/sql/aggregates.py index 0e1794e0a9..8542a330c6 100644 --- a/django/db/models/sql/aggregates.py +++ b/django/db/models/sql/aggregates.py @@ -5,6 +5,10 @@ import copy from django.db.models.fields import IntegerField, FloatField + +__all__ = ['Aggregate', 'Avg', 'Count', 'Max', 'Min', 'StdDev', 'Sum', 'Variance'] + + # Fake fields used to identify aggregate types in data-conversion operations. ordinal_aggregate_field = IntegerField() computed_aggregate_field = FloatField() -- cgit v1.3