Fixed #17830 -- Modified list_filter on DateTimeFields to account for the new time zone support. Thanks Glenn Washburn for the report and Jannis Leidel for the review.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17670 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f95141abcc
commit
bf0abe0ea6
|
@ -11,6 +11,7 @@ from django.db import models
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from django.contrib.admin.util import (get_model_from_relation,
|
from django.contrib.admin.util import (get_model_from_relation,
|
||||||
reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value)
|
reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value)
|
||||||
|
@ -282,44 +283,49 @@ class DateFieldListFilter(FieldListFilter):
|
||||||
self.field_generic = '%s__' % field_path
|
self.field_generic = '%s__' % field_path
|
||||||
self.date_params = dict([(k, v) for k, v in params.items()
|
self.date_params = dict([(k, v) for k, v in params.items()
|
||||||
if k.startswith(self.field_generic)])
|
if k.startswith(self.field_generic)])
|
||||||
today = datetime.date.today()
|
|
||||||
one_week_ago = today - datetime.timedelta(days=7)
|
now = timezone.now()
|
||||||
today_str = str(today)
|
# When time zone support is enabled, convert "now" to the user's time
|
||||||
|
# zone so Django's definition of "Today" matches what the user expects.
|
||||||
|
if now.tzinfo is not None:
|
||||||
|
current_tz = timezone.get_current_timezone()
|
||||||
|
now = now.astimezone(current_tz)
|
||||||
|
if hasattr(current_tz, 'normalize'):
|
||||||
|
# available for pytz time zones
|
||||||
|
now = current_tz.normalize(now)
|
||||||
|
|
||||||
if isinstance(field, models.DateTimeField):
|
if isinstance(field, models.DateTimeField):
|
||||||
today_str += ' 23:59:59'
|
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
self.lookup_kwarg_year = '%s__year' % field_path
|
else: # field is a models.DateField
|
||||||
self.lookup_kwarg_month = '%s__month' % field_path
|
today = now.date()
|
||||||
self.lookup_kwarg_day = '%s__day' % field_path
|
tomorrow = today + datetime.timedelta(days=1)
|
||||||
self.lookup_kwarg_past_7_days_gte = '%s__gte' % field_path
|
|
||||||
self.lookup_kwarg_past_7_days_lte = '%s__lte' % field_path
|
self.lookup_kwarg_since = '%s__gte' % field_path
|
||||||
|
self.lookup_kwarg_until = '%s__lt' % field_path
|
||||||
self.links = (
|
self.links = (
|
||||||
(_('Any date'), {}),
|
(_('Any date'), {}),
|
||||||
(_('Today'), {
|
(_('Today'), {
|
||||||
self.lookup_kwarg_year: str(today.year),
|
self.lookup_kwarg_since: str(today),
|
||||||
self.lookup_kwarg_month: str(today.month),
|
self.lookup_kwarg_until: str(tomorrow),
|
||||||
self.lookup_kwarg_day: str(today.day),
|
|
||||||
}),
|
}),
|
||||||
(_('Past 7 days'), {
|
(_('Past 7 days'), {
|
||||||
self.lookup_kwarg_past_7_days_gte: str(one_week_ago),
|
self.lookup_kwarg_since: str(today - datetime.timedelta(days=7)),
|
||||||
self.lookup_kwarg_past_7_days_lte: today_str,
|
self.lookup_kwarg_until: str(tomorrow),
|
||||||
}),
|
}),
|
||||||
(_('This month'), {
|
(_('This month'), {
|
||||||
self.lookup_kwarg_year: str(today.year),
|
self.lookup_kwarg_since: str(today.replace(day=1)),
|
||||||
self.lookup_kwarg_month: str(today.month),
|
self.lookup_kwarg_until: str(tomorrow),
|
||||||
}),
|
}),
|
||||||
(_('This year'), {
|
(_('This year'), {
|
||||||
self.lookup_kwarg_year: str(today.year),
|
self.lookup_kwarg_since: str(today.replace(month=1, day=1)),
|
||||||
|
self.lookup_kwarg_until: str(tomorrow),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
super(DateFieldListFilter, self).__init__(
|
super(DateFieldListFilter, self).__init__(
|
||||||
field, request, params, model, model_admin, field_path)
|
field, request, params, model, model_admin, field_path)
|
||||||
|
|
||||||
def expected_parameters(self):
|
def expected_parameters(self):
|
||||||
return [
|
return [self.lookup_kwarg_since, self.lookup_kwarg_until]
|
||||||
self.lookup_kwarg_year, self.lookup_kwarg_month,
|
|
||||||
self.lookup_kwarg_day, self.lookup_kwarg_past_7_days_gte,
|
|
||||||
self.lookup_kwarg_past_7_days_lte
|
|
||||||
]
|
|
||||||
|
|
||||||
def choices(self, cl):
|
def choices(self, cl):
|
||||||
for title, param_dict in self.links:
|
for title, param_dict in self.links:
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.contrib.auth.admin import UserAdmin
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.test import TestCase, RequestFactory
|
from django.test import TestCase, RequestFactory
|
||||||
|
from django.test.utils import override_settings
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
|
|
||||||
from .models import Book
|
from .models import Book
|
||||||
|
@ -115,6 +116,7 @@ class ListFiltersTests(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.today = datetime.date.today()
|
self.today = datetime.date.today()
|
||||||
|
self.tomorrow = self.today + datetime.timedelta(days=1)
|
||||||
self.one_week_ago = self.today - datetime.timedelta(days=7)
|
self.one_week_ago = self.today - datetime.timedelta(days=7)
|
||||||
|
|
||||||
self.request_factory = RequestFactory()
|
self.request_factory = RequestFactory()
|
||||||
|
@ -143,9 +145,8 @@ class ListFiltersTests(TestCase):
|
||||||
request = self.request_factory.get('/')
|
request = self.request_factory.get('/')
|
||||||
changelist = self.get_changelist(request, Book, modeladmin)
|
changelist = self.get_changelist(request, Book, modeladmin)
|
||||||
|
|
||||||
request = self.request_factory.get('/', {'date_registered__year': self.today.year,
|
request = self.request_factory.get('/', {'date_registered__gte': self.today,
|
||||||
'date_registered__month': self.today.month,
|
'date_registered__lt': self.tomorrow})
|
||||||
'date_registered__day': self.today.day})
|
|
||||||
changelist = self.get_changelist(request, Book, modeladmin)
|
changelist = self.get_changelist(request, Book, modeladmin)
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
|
@ -157,13 +158,12 @@ class ListFiltersTests(TestCase):
|
||||||
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
||||||
choice = select_by(filterspec.choices(changelist), "display", "Today")
|
choice = select_by(filterspec.choices(changelist), "display", "Today")
|
||||||
self.assertEqual(choice['selected'], True)
|
self.assertEqual(choice['selected'], True)
|
||||||
self.assertEqual(choice['query_string'], '?date_registered__day=%s'
|
self.assertEqual(choice['query_string'], '?date_registered__gte=%s'
|
||||||
'&date_registered__month=%s'
|
'&date_registered__lt=%s'
|
||||||
'&date_registered__year=%s'
|
% (self.today, self.tomorrow))
|
||||||
% (self.today.day, self.today.month, self.today.year))
|
|
||||||
|
|
||||||
request = self.request_factory.get('/', {'date_registered__year': self.today.year,
|
request = self.request_factory.get('/', {'date_registered__gte': self.today.replace(day=1),
|
||||||
'date_registered__month': self.today.month})
|
'date_registered__lt': self.tomorrow})
|
||||||
changelist = self.get_changelist(request, Book, modeladmin)
|
changelist = self.get_changelist(request, Book, modeladmin)
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
|
@ -179,11 +179,12 @@ class ListFiltersTests(TestCase):
|
||||||
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
||||||
choice = select_by(filterspec.choices(changelist), "display", "This month")
|
choice = select_by(filterspec.choices(changelist), "display", "This month")
|
||||||
self.assertEqual(choice['selected'], True)
|
self.assertEqual(choice['selected'], True)
|
||||||
self.assertEqual(choice['query_string'], '?date_registered__month=%s'
|
self.assertEqual(choice['query_string'], '?date_registered__gte=%s'
|
||||||
'&date_registered__year=%s'
|
'&date_registered__lt=%s'
|
||||||
% (self.today.month, self.today.year))
|
% (self.today.replace(day=1), self.tomorrow))
|
||||||
|
|
||||||
request = self.request_factory.get('/', {'date_registered__year': self.today.year})
|
request = self.request_factory.get('/', {'date_registered__gte': self.today.replace(month=1, day=1),
|
||||||
|
'date_registered__lt': self.tomorrow})
|
||||||
changelist = self.get_changelist(request, Book, modeladmin)
|
changelist = self.get_changelist(request, Book, modeladmin)
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
|
@ -199,11 +200,12 @@ class ListFiltersTests(TestCase):
|
||||||
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
self.assertEqual(force_unicode(filterspec.title), u'date registered')
|
||||||
choice = select_by(filterspec.choices(changelist), "display", "This year")
|
choice = select_by(filterspec.choices(changelist), "display", "This year")
|
||||||
self.assertEqual(choice['selected'], True)
|
self.assertEqual(choice['selected'], True)
|
||||||
self.assertEqual(choice['query_string'], '?date_registered__year=%s'
|
self.assertEqual(choice['query_string'], '?date_registered__gte=%s'
|
||||||
% (self.today.year))
|
'&date_registered__lt=%s'
|
||||||
|
% (self.today.replace(month=1, day=1), self.tomorrow))
|
||||||
|
|
||||||
request = self.request_factory.get('/', {'date_registered__gte': str(self.one_week_ago),
|
request = self.request_factory.get('/', {'date_registered__gte': str(self.one_week_ago),
|
||||||
'date_registered__lte': str(self.today)})
|
'date_registered__lt': str(self.tomorrow)})
|
||||||
changelist = self.get_changelist(request, Book, modeladmin)
|
changelist = self.get_changelist(request, Book, modeladmin)
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
|
@ -216,8 +218,13 @@ class ListFiltersTests(TestCase):
|
||||||
choice = select_by(filterspec.choices(changelist), "display", "Past 7 days")
|
choice = select_by(filterspec.choices(changelist), "display", "Past 7 days")
|
||||||
self.assertEqual(choice['selected'], True)
|
self.assertEqual(choice['selected'], True)
|
||||||
self.assertEqual(choice['query_string'], '?date_registered__gte=%s'
|
self.assertEqual(choice['query_string'], '?date_registered__gte=%s'
|
||||||
'&date_registered__lte=%s'
|
'&date_registered__lt=%s'
|
||||||
% (str(self.one_week_ago), str(self.today)))
|
% (str(self.one_week_ago), str(self.tomorrow)))
|
||||||
|
|
||||||
|
@override_settings(USE_TZ=True)
|
||||||
|
def test_datefieldlistfilter_with_time_zone_support(self):
|
||||||
|
# Regression for #17830
|
||||||
|
self.test_datefieldlistfilter()
|
||||||
|
|
||||||
def test_allvaluesfieldlistfilter(self):
|
def test_allvaluesfieldlistfilter(self):
|
||||||
modeladmin = BookAdmin(Book, site)
|
modeladmin = BookAdmin(Book, site)
|
||||||
|
|
Loading…
Reference in New Issue