Fixed #31620 -- Added support for %V format to WeekMixin/WeekArchiveView.

Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
Hasan Ramezani 2020-06-25 23:00:51 +02:00 committed by Mariusz Felisiak
parent d2c135da4c
commit 8984cab8a8
6 changed files with 55 additions and 9 deletions

View File

@ -218,7 +218,7 @@ class WeekMixin:
The first day according to the week format is 0 and the last day is 6. The first day according to the week format is 0 and the last day is 6.
""" """
week_format = self.get_week_format() week_format = self.get_week_format()
if week_format == '%W': # week starts on Monday if week_format in {'%W', '%V'}: # week starts on Monday
return date.weekday() return date.weekday()
elif week_format == '%U': # week starts on Sunday elif week_format == '%U': # week starts on Sunday
return (date.weekday() + 1) % 7 return (date.weekday() + 1) % 7
@ -485,7 +485,7 @@ class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
date_field = self.get_date_field() date_field = self.get_date_field()
week_format = self.get_week_format() week_format = self.get_week_format()
week_choices = {'%W': '1', '%U': '0'} week_choices = {'%W': '1', '%U': '0', '%V': '1'}
try: try:
week_start = week_choices[week_format] week_start = week_choices[week_format]
except KeyError: except KeyError:
@ -493,10 +493,15 @@ class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
week_format, week_format,
', '.join(sorted(week_choices)), ', '.join(sorted(week_choices)),
)) ))
date = _date_from_string(year, self.get_year_format(), year_format = self.get_year_format()
week_start, '%w', if week_format == '%V' and year_format != '%G':
week, week_format) raise ValueError(
"ISO week directive '%s' is incompatible with the year "
"directive '%s'. Use the ISO year '%%G' instead." % (
week_format, year_format,
)
)
date = _date_from_string(year, year_format, week_start, '%w', week, week_format)
since = self._make_date_lookup_arg(date) since = self._make_date_lookup_arg(date)
until = self._make_date_lookup_arg(self._get_next_week(date)) until = self._make_date_lookup_arg(self._get_next_week(date))
lookup_kwargs = { lookup_kwargs = {

View File

@ -342,6 +342,12 @@ views for displaying drilldown pages for date-based data.
* ``'%W'``: Similar to ``'%U'``, except it assumes that the week * ``'%W'``: Similar to ``'%U'``, except it assumes that the week
begins on Monday. This is not the same as the ISO 8601 week number. begins on Monday. This is not the same as the ISO 8601 week number.
* ``'%V'``: ISO 8601 week number where the week begins on Monday.
.. versionadded:: 3.2
Support for the ``'%V'`` week format was added.
**Example myapp/views.py**:: **Example myapp/views.py**::
from django.views.generic.dates import WeekArchiveView from django.views.generic.dates import WeekArchiveView

View File

@ -180,7 +180,12 @@ Date-based mixins
The :func:`~time.strftime` format to use when parsing the week. By The :func:`~time.strftime` format to use when parsing the week. By
default, this is ``'%U'``, which means the week starts on Sunday. Set default, this is ``'%U'``, which means the week starts on Sunday. Set
it to ``'%W'`` if your week starts on Monday. it to ``'%W'`` or ``'%V'`` (ISO 8601 week) if your week starts on
Monday.
.. versionadded:: 3.2
Support for the ``'%V'`` week format was added.
.. attribute:: week .. attribute:: week

View File

@ -166,7 +166,10 @@ Forms
Generic Views Generic Views
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
* ... * The ``week_format`` attributes of
:class:`~django.views.generic.dates.WeekMixin` and
:class:`~django.views.generic.dates.WeekArchiveView` now support the
``'%V'`` ISO 8601 week format.
Internationalization Internationalization
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

View File

@ -538,10 +538,29 @@ class WeekArchiveViewTests(TestDataMixin, TestCase):
self.assertEqual(res.status_code, 200) self.assertEqual(res.status_code, 200)
self.assertEqual(res.context['week'], datetime.date(2008, 9, 29)) self.assertEqual(res.context['week'], datetime.date(2008, 9, 29))
def test_week_iso_format(self):
res = self.client.get('/dates/books/2008/week/40/iso_format/')
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/book_archive_week.html')
self.assertEqual(
list(res.context['book_list']),
[Book.objects.get(pubdate=datetime.date(2008, 10, 1))],
)
self.assertEqual(res.context['week'], datetime.date(2008, 9, 29))
def test_unknown_week_format(self): def test_unknown_week_format(self):
with self.assertRaisesMessage(ValueError, "Unknown week format '%T'. Choices are: %U, %W"): msg = "Unknown week format '%T'. Choices are: %U, %V, %W"
with self.assertRaisesMessage(ValueError, msg):
self.client.get('/dates/books/2008/week/39/unknown_week_format/') self.client.get('/dates/books/2008/week/39/unknown_week_format/')
def test_incompatible_iso_week_format_view(self):
msg = (
"ISO week directive '%V' is incompatible with the year directive "
"'%Y'. Use the ISO year '%G' instead."
)
with self.assertRaisesMessage(ValueError, msg):
self.client.get('/dates/books/2008/week/40/invalid_iso_week_year_format/')
def test_datetime_week_view(self): def test_datetime_week_view(self):
BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0))
res = self.client.get('/dates/booksignings/2008/week/13/') res = self.client.get('/dates/booksignings/2008/week/13/')

View File

@ -190,6 +190,14 @@ urlpatterns = [
'dates/books/<int:year>/week/<int:week>/unknown_week_format/', 'dates/books/<int:year>/week/<int:week>/unknown_week_format/',
views.BookWeekArchive.as_view(week_format='%T'), views.BookWeekArchive.as_view(week_format='%T'),
), ),
path(
'dates/books/<int:year>/week/<int:week>/iso_format/',
views.BookWeekArchive.as_view(year_format='%G', week_format='%V'),
),
path(
'dates/books/<int:year>/week/<int:week>/invalid_iso_week_year_format/',
views.BookWeekArchive.as_view(week_format='%V'),
),
path('dates/booksignings/<int:year>/week/<int:week>/', views.BookSigningWeekArchive.as_view()), path('dates/booksignings/<int:year>/week/<int:week>/', views.BookSigningWeekArchive.as_view()),
# DayArchiveView # DayArchiveView