From 757945b47de45b6eaa0b0e14f87936261a60d227 Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Sat, 2 Nov 2013 18:57:35 -0500 Subject: Fixed failing test around DST change. The timezone arithmetic done in JS can be off by one hour around DST change. We work around this issue by adding one extra hour to the test error margin when we detect a DST change is near. Refs #20663. --- tests/admin_widgets/tests.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index 0aa8e98933..e6f33b04e0 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 @@ -635,6 +640,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): @@ -654,9 +660,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/')) -- 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 'tests') 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