From 3b2993ed04f200a89c2d49590131c97c8974e9ac Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Thu, 24 May 2012 13:02:19 +0200 Subject: [PATCH] Fixed #18353 -- Inconsistency in date-based CBVs. --- django/views/generic/dates.py | 18 +++++++++++++++++- docs/ref/class-based-views.txt | 10 +++++++++- docs/releases/1.5.txt | 14 +++++++++++++- tests/regressiontests/generic_views/dates.py | 12 ++++++++++-- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py index 804e03dd20..3e6ab0fa0c 100644 --- a/django/views/generic/dates.py +++ b/django/views/generic/dates.py @@ -37,6 +37,18 @@ class YearMixin(object): raise Http404(_(u"No year specified")) return year + def get_next_year(self, date): + """ + Get the next valid year. + """ + return _get_next_prev(self, date, is_previous=False, period='year') + + def get_previous_year(self, date): + """ + Get the previous valid year. + """ + return _get_next_prev(self, date, is_previous=True, period='year') + def _get_next_year(self, date): """ Return the start date of the next interval. @@ -419,7 +431,11 @@ class BaseYearArchiveView(YearMixin, BaseDateListView): # to find information about the model. qs = qs.none() - return (date_list, qs, {'year': year}) + return (date_list, qs, { + 'year': date, + 'next_year': self.get_next_year(date), + 'previous_year': self.get_previous_year(date), + }) def get_make_object_list(self): """ diff --git a/docs/ref/class-based-views.txt b/docs/ref/class-based-views.txt index b3f6b19e99..acd9db2d66 100644 --- a/docs/ref/class-based-views.txt +++ b/docs/ref/class-based-views.txt @@ -1171,7 +1171,15 @@ YearArchiveView have objects available according to ``queryset``, represented as ``datetime.datetime`` objects, in ascending order. - * ``year``: The given year, as a four-character string. + * ``year``: A ``datetime.date`` object representing the given year. + + * ``next_year``: A ``datetime.date`` object representing the first day + of the next year. If the next year is in the future, this will be + ``None``. + + * ``previous_year``: A ``datetime.date`` object representing the first + day of the previous year. Unlike ``next_year``, this will never be + ``None``. **Notes** diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index 51e64bd202..e11991b257 100644 --- a/docs/releases/1.5.txt +++ b/docs/releases/1.5.txt @@ -71,6 +71,18 @@ Backwards incompatible changes in 1.5 deprecation timeline for a given feature, its removal may appear as a backwards incompatible change. +Context in year archive class-based views +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For consistency with the other date-based generic views, +:class:`~django.views.generic.dates.YearArchiveView` now passes ``year`` in +the context as a :class:`datetime.date` rather than a string. If you are +using ``{{ year }}`` in your templates, you must replace it with ``{{ +year|date:"Y" }}``. + +``next_year`` and ``previous_year`` were also added in the context. They are +calculated according to ``allow_empty`` and ``allow_future``. + Features deprecated in 1.5 ========================== @@ -86,4 +98,4 @@ our own copy of ``simplejson``. You can safely change any use of ~~~~~~~~~~~~~~~~~~~~~~ The :func:`~django.utils.itercompat.product` function has been deprecated. Use -the built-in `itertools.product` instead. +the built-in :func:`itertools.product` instead. diff --git a/tests/regressiontests/generic_views/dates.py b/tests/regressiontests/generic_views/dates.py index 8f82dddbcf..ad65fd9f10 100644 --- a/tests/regressiontests/generic_views/dates.py +++ b/tests/regressiontests/generic_views/dates.py @@ -115,9 +115,13 @@ class YearArchiveViewTests(TestCase): res = self.client.get('/dates/books/2008/') self.assertEqual(res.status_code, 200) self.assertEqual(list(res.context['date_list']), [datetime.datetime(2008, 10, 1)]) - self.assertEqual(res.context['year'], '2008') + self.assertEqual(res.context['year'], datetime.date(2008, 1, 1)) self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + # Since allow_empty=False, next/prev years must be valid (#7164) + self.assertEqual(res.context['next_year'], None) + self.assertEqual(res.context['previous_year'], datetime.date(2006, 1, 1)) + def test_year_view_make_object_list(self): res = self.client.get('/dates/books/2006/make_object_list/') self.assertEqual(res.status_code, 200) @@ -134,6 +138,10 @@ class YearArchiveViewTests(TestCase): self.assertEqual(list(res.context['date_list']), []) self.assertEqual(list(res.context['book_list']), []) + # Since allow_empty=True, next/prev are allowed to be empty years (#7164) + self.assertEqual(res.context['next_year'], datetime.date(2000, 1, 1)) + self.assertEqual(res.context['previous_year'], datetime.date(1998, 1, 1)) + def test_year_view_allow_future(self): # Create a new book in the future year = datetime.date.today().year + 1 @@ -162,7 +170,7 @@ class YearArchiveViewTests(TestCase): def test_no_duplicate_query(self): # Regression test for #18354 - with self.assertNumQueries(2): + with self.assertNumQueries(4): self.client.get('/dates/books/2008/reverse/') def test_datetime_year_view(self):