| 
1 | 1 | import re  | 
2 | 2 | from collections.abc import MutableMapping  | 
 | 3 | +from datetime import datetime  | 
 | 4 | +from zoneinfo import ZoneInfo  | 
3 | 5 | 
 
  | 
4 | 6 | import pytest  | 
5 | 7 | from django.core.cache import cache  | 
@@ -488,6 +490,85 @@ class TestSerializer(serializers.Serializer):  | 
488 | 490 |  assert rendered == ''  | 
489 | 491 | 
 
  | 
490 | 492 | 
 
  | 
 | 493 | +class TestDateTimeFieldHTMLFormRender(TestCase):  | 
 | 494 | + """  | 
 | 495 | + Default USE_TZ is True.  | 
 | 496 | + Default TIME_ZONE is 'America/Chicago'.  | 
 | 497 | + """  | 
 | 498 | + | 
 | 499 | + def _assert_datetime_rendering(self, appointment, expected, datetimefield_kwargs=None):  | 
 | 500 | + datetimefield_kwargs = datetimefield_kwargs or {}  | 
 | 501 | + | 
 | 502 | + class TestSerializer(serializers.Serializer):  | 
 | 503 | + appointment = serializers.DateTimeField(**datetimefield_kwargs)  | 
 | 504 | + | 
 | 505 | + serializer = TestSerializer(data={"appointment": appointment})  | 
 | 506 | + serializer.is_valid()  | 
 | 507 | + renderer = HTMLFormRenderer()  | 
 | 508 | + field = serializer['appointment']  | 
 | 509 | + rendered = renderer.render_field(field, {})  | 
 | 510 | + expected_html = (  | 
 | 511 | + '<input name="appointment" class="form-control" '  | 
 | 512 | + f'type="datetime-local" value="{expected}">'  | 
 | 513 | + )  | 
 | 514 | + | 
 | 515 | + self.assertInHTML(expected_html, rendered)  | 
 | 516 | + | 
 | 517 | + def test_datetime_field_rendering_milliseconds(self):  | 
 | 518 | + self._assert_datetime_rendering(  | 
 | 519 | + datetime(2024, 12, 24, 0, 55, 30, 345678), "2024-12-24T00:55:30.345"  | 
 | 520 | + )  | 
 | 521 | + | 
 | 522 | + def test_datetime_field_rendering_no_seconds_and_no_milliseconds(self):  | 
 | 523 | + self._assert_datetime_rendering(  | 
 | 524 | + datetime(2024, 12, 24, 0, 55, 0, 0), "2024-12-24T00:55:00.000"  | 
 | 525 | + )  | 
 | 526 | + | 
 | 527 | + def test_datetime_field_rendering_with_format_as_none(self):  | 
 | 528 | + self._assert_datetime_rendering(  | 
 | 529 | + datetime(2024, 12, 24, 0, 55, 30, 345678),  | 
 | 530 | + "2024-12-24T00:55:30.345",  | 
 | 531 | + {"format": None}  | 
 | 532 | + )  | 
 | 533 | + | 
 | 534 | + def test_datetime_field_rendering_with_format(self):  | 
 | 535 | + self._assert_datetime_rendering(  | 
 | 536 | + datetime(2024, 12, 24, 0, 55, 30, 345678),  | 
 | 537 | + "2024-12-24T00:55:00.000",  | 
 | 538 | + {"format": "%a %d %b %Y, %I:%M%p"}  | 
 | 539 | + )  | 
 | 540 | + | 
 | 541 | + # New project templates default to 'UTC'.  | 
 | 542 | + @override_settings(TIME_ZONE='UTC')  | 
 | 543 | + def test_datetime_field_rendering_utc(self):  | 
 | 544 | + self._assert_datetime_rendering(  | 
 | 545 | + datetime(2024, 12, 24, 0, 55, 30, 345678),  | 
 | 546 | + "2024-12-24T00:55:30.345"  | 
 | 547 | + )  | 
 | 548 | + | 
 | 549 | + @override_settings(REST_FRAMEWORK={'DATETIME_FORMAT': '%a %d %b %Y, %I:%M%p'})  | 
 | 550 | + def test_datetime_field_rendering_with_custom_datetime_format(self):  | 
 | 551 | + self._assert_datetime_rendering(  | 
 | 552 | + datetime(2024, 12, 24, 0, 55, 30, 345678),  | 
 | 553 | + "2024-12-24T00:55:00.000"  | 
 | 554 | + )  | 
 | 555 | + | 
 | 556 | + @override_settings(REST_FRAMEWORK={'DATETIME_FORMAT': None})  | 
 | 557 | + def test_datetime_field_rendering_datetime_format_is_none(self):  | 
 | 558 | + self._assert_datetime_rendering(  | 
 | 559 | + datetime(2024, 12, 24, 0, 55, 30, 345678),  | 
 | 560 | + "2024-12-24T00:55:30.345"  | 
 | 561 | + )  | 
 | 562 | + | 
 | 563 | + # Enforce it in True because in Django versions under 4.2 was False by default.  | 
 | 564 | + @override_settings(USE_TZ=True)  | 
 | 565 | + def test_datetime_field_rendering_timezone_aware_datetime(self):  | 
 | 566 | + self._assert_datetime_rendering(  | 
 | 567 | + datetime(2024, 12, 24, 0, 55, 30, 345678, tzinfo=ZoneInfo('Asia/Tokyo')), # +09:00  | 
 | 568 | + "2024-12-23T09:55:30.345" # Rendered in -06:00  | 
 | 569 | + )  | 
 | 570 | + | 
 | 571 | + | 
491 | 572 | class TestHTMLFormRenderer(TestCase):  | 
492 | 573 |  def setUp(self):  | 
493 | 574 |  class TestSerializer(serializers.Serializer):  | 
 | 
0 commit comments