diff --git a/publik_django_templatetags/wcs/context_processors.py b/publik_django_templatetags/wcs/context_processors.py index 30c24a0..004c172 100644 --- a/publik_django_templatetags/wcs/context_processors.py +++ b/publik_django_templatetags/wcs/context_processors.py @@ -14,7 +14,11 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import datetime + +from django.utils.dateparse import parse_date, parse_datetime from django.utils.http import urlencode +from django.utils.timezone import is_naive, make_aware from requests.exceptions import RequestException from publik_django_templatetags.utils.requests_wrapper import requests @@ -103,6 +107,24 @@ class LazyCardDefObjectsManager: qs._filters['include-workflow-data'] = 'on' return qs + def get_at(self, value): + qs = self._clone() + if isinstance(value, str): + parsed = parse_datetime(value) + if not parsed: + parsed = parse_date(value) + if parsed: + value = parsed + if isinstance(value, datetime.datetime): + if is_naive(value): + value = make_aware(value) + value = value.isoformat() + elif isinstance(value, datetime.date): + value = make_aware(datetime.datetime.combine(value, datetime.datetime.min.time())).isoformat() + if value: + qs._filters['at'] = value + return qs + def access_control(self, user): qs = self._clone() qs._user = user diff --git a/publik_django_templatetags/wcs/templatetags/wcs.py b/publik_django_templatetags/wcs/templatetags/wcs.py index c8b25f7..dfd6982 100644 --- a/publik_django_templatetags/wcs/templatetags/wcs.py +++ b/publik_django_templatetags/wcs/templatetags/wcs.py @@ -91,6 +91,11 @@ def include_workflow_data(queryset): return None +@register.filter +def get_at(queryset, value): + return queryset.get_at(value) + + @register.filter def access_control(queryset, user): try: diff --git a/tests/test_wcs.py b/tests/test_wcs.py index 9d33041..12da3c4 100644 --- a/tests/test_wcs.py +++ b/tests/test_wcs.py @@ -1,6 +1,8 @@ import copy +import datetime import json from unittest import mock +from urllib.parse import parse_qs, urlparse import pytest from django.template import Context, Template @@ -184,6 +186,60 @@ def test_include_filters(mock_send, context, nocache): assert mock_send.call_args_list == [] +@mock.patch('requests.Session.send', side_effect=mocked_requests_send) +def test_at(mock_send, settings, freezer, context, nocache): + settings.TIME_ZONE = 'Europe/Paris' + freezer.move_to('2022-10-17 12:21') + + def get_at_param(url): + parsed = parse_qs(urlparse(url).query) + if 'at' not in parsed: + return + return parsed['at'][0] + + t = Template('{{ cards|objects:"foo"|list }}') + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) is None + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:""|list }}') + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) is None + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:none|list }}') + context['none'] = None + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) is None + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:"bad-value"|list }}') + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) == 'bad-value' + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:"2022-10-17"|list }}') + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) == '2022-10-17T00:00:00+02:00' + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:"2022-10-17 23:20"|list }}') + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) == '2022-10-17T23:20:00+02:00' + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:a_date|list }}') + context['a_date'] = datetime.date.today() + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) == '2022-10-17T00:00:00+02:00' + + mock_send.reset_mock() + t = Template('{{ cards|objects:"foo"|get_at:a_datetime|list }}') + context['a_datetime'] = datetime.datetime.now() + t.render(context) + assert get_at_param(mock_send.call_args_list[0][0][0].url) == '2022-10-17T12:21:00+02:00' + + @mock.patch('requests.Session.send', side_effect=mocked_requests_send) def test_errors(mock_send, context, nocache): t = Template('{{ cards|objects:"foo"|list }}') diff --git a/tox.ini b/tox.ini index a1e6f23..62b76f3 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,7 @@ deps = pytest pytest-cov pytest-django + pytest-freezegun WebTest psycopg2-binary<2.9 psycopg2<2.9