diff --git a/django/contrib/gis/db/models/sql/aggregates.py b/django/contrib/gis/db/models/sql/aggregates.py
index f8f3ed1eb4..c0a7d894eb 100644
--- a/django/contrib/gis/db/models/sql/aggregates.py
+++ b/django/contrib/gis/db/models/sql/aggregates.py
@@ -1,7 +1,11 @@
-from django.db.models.sql.aggregates import Aggregate
+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__ = ['Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] + aggregates.__all__
+
+
 class GeoAggregate(Aggregate):
     # Default SQL template for spatial aggregates.
     sql_template = '%(function)s(%(field)s)'
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()
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/admin_widgets/tests.py b/tests/admin_widgets/tests.py
index 0dec3a2cfa..04fe083eea 100644
--- a/tests/admin_widgets/tests.py
+++ b/tests/admin_widgets/tests.py
@@ -2,7 +2,12 @@
 from __future__ import unicode_literals
 
 from datetime import datetime, timedelta
-from unittest import TestCase
+from unittest import TestCase, skipIf
+
+try:
+    import pytz
+except ImportError:
+    pytz = None
 
 from django import forms
 from django.conf import settings
@@ -641,6 +646,7 @@ class DateTimePickerSeleniumIETests(DateTimePickerSeleniumFirefoxTests):
     webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver'
 
 
+@skipIf(pytz is None, "this test requires pytz")
 @override_settings(TIME_ZONE='Asia/Singapore')
 @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
 class DateTimePickerShortcutsSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
@@ -660,9 +666,18 @@ class DateTimePickerShortcutsSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase
         """
         self.admin_login(username='super', password='secret', login_url='/')
 
-        now = datetime.now()
         error_margin = timedelta(seconds=10)
 
+        # If we are neighbouring a DST, we add an hour of error margin.
+        tz = pytz.timezone('America/Chicago')
+        utc_now = datetime.now(pytz.utc)
+        tz_yesterday = (utc_now - timedelta(days=1)).astimezone(tz).tzname()
+        tz_tomorrow = (utc_now + timedelta(days=1)).astimezone(tz).tzname()
+        if tz_yesterday != tz_tomorrow:
+            error_margin += timedelta(hours=1)
+
+        now = datetime.now()
+
         self.selenium.get('%s%s' % (self.live_server_url,
             '/admin_widgets/member/add/'))
 
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 5e443011c2..2af5b5a07d 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -828,6 +828,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):