-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Fixed #5363 -- HTML5 datetime-local valid format HTMLFormRenderer #9365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
29e41f1
85ca282
b39982b
0c2b20c
34db0cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -342,8 +342,12 @@ def render_field(self, field, parent_style): | |||||||||
# Get a clone of the field with text-only value representation. | ||||||||||
field = field.as_form_field() | ||||||||||
|
||||||||||
if style.get('input_type') == 'datetime-local' and isinstance(field.value, str): | ||||||||||
field.value = field.value.rstrip('Z') | ||||||||||
if style.get('input_type') == 'datetime-local': | ||||||||||
# The format of an input type="datetime-local" is "yyyy-MM-ddThh:mm" | ||||||||||
# followed by optional ":ss" or ":ss.SSS", so keep only the first three | ||||||||||
# digits of milliseconds to avoid browser console error. | ||||||||||
datetime_value = field._field.parent.validated_data.get(field.field_name) | ||||||||||
field.value = datetime_value.replace(tzinfo=None).isoformat(timespec="milliseconds").rstrip('Z') | ||||||||||
|
||||||||||
Comment on lines
+350
to
351
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code will raise an AttributeError if
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mgaligniana please cross check this suggestion, and come up with a better solution if possible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perfect! I'll do, thanks! |
||||||||||
if 'template' in style: | ||||||||||
template_name = style['template'] | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import re | ||
from collections.abc import MutableMapping | ||
from datetime import datetime | ||
|
||
import pytest | ||
from django.core.cache import cache | ||
|
@@ -488,6 +489,89 @@ class TestSerializer(serializers.Serializer): | |
assert rendered == '' | ||
|
||
|
||
class TestDateTimeFieldHTMLFormRender(TestCase): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to add a couple of test cases with some non-naive datetimes, with a timezone specified. Could try with UTC and another timezone where the offset is non-zero There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! So I've added a docstring to let know that config variables are set in
And added a fourth test where Is that correct? |
||
""" | ||
Default USE_TZ is True. | ||
Default TIME_ZONE is 'America/Chicago'. | ||
""" | ||
|
||
def test_datetime_field_rendering_milliseconds(self): | ||
class TestSerializer(serializers.Serializer): | ||
appointment = serializers.DateTimeField() | ||
|
||
appointment = datetime(2024, 12, 24, 0, 55, 30, 345678) | ||
serializer = TestSerializer(data={"appointment": appointment}) | ||
serializer.is_valid() | ||
renderer = HTMLFormRenderer() | ||
field = serializer['appointment'] | ||
rendered = renderer.render_field(field, {}) | ||
self.assertInHTML( | ||
'<input name="appointment" class="form-control" type="datetime-local" value="2024-12-24T00:55:30.345">', | ||
rendered | ||
) | ||
|
||
def test_datetime_field_rendering_no_milliseconds(self): | ||
class TestSerializer(serializers.Serializer): | ||
appointment = serializers.DateTimeField() | ||
|
||
appointment = datetime(2024, 12, 24, 0, 55, 30, 0) | ||
serializer = TestSerializer(data={"appointment": appointment}) | ||
serializer.is_valid() | ||
renderer = HTMLFormRenderer() | ||
field = serializer['appointment'] | ||
rendered = renderer.render_field(field, {}) | ||
self.assertInHTML( | ||
'<input name="appointment" class="form-control" type="datetime-local" value="2024-12-24T00:55:30.000">', | ||
rendered | ||
) | ||
|
||
def test_datetime_field_rendering_no_seconds_and_no_milliseconds(self): | ||
class TestSerializer(serializers.Serializer): | ||
appointment = serializers.DateTimeField() | ||
|
||
appointment = datetime(2024, 12, 24, 0, 55, 0, 0) | ||
serializer = TestSerializer(data={"appointment": appointment}) | ||
serializer.is_valid() | ||
renderer = HTMLFormRenderer() | ||
field = serializer['appointment'] | ||
rendered = renderer.render_field(field, {}) | ||
self.assertInHTML( | ||
'<input name="appointment" class="form-control" type="datetime-local" value="2024-12-24T00:55:00.000">', | ||
rendered | ||
) | ||
|
||
def test_datetime_field_rendering_with_format(self): | ||
class TestSerializer(serializers.Serializer): | ||
appointment = serializers.DateTimeField(format='%a %d %b %Y, %I:%M%p') | ||
|
||
appointment = datetime(2024, 12, 24, 0, 55, 30, 345678) | ||
serializer = TestSerializer(data={"appointment": appointment}) | ||
serializer.is_valid() | ||
renderer = HTMLFormRenderer() | ||
field = serializer['appointment'] | ||
rendered = renderer.render_field(field, {}) | ||
self.assertInHTML( | ||
'<input name="appointment" class="form-control" type="datetime-local" value="2024-12-24T00:55:30.345">', | ||
rendered | ||
) | ||
|
||
@override_settings(TIME_ZONE='UTC', USE_TZ=True) | ||
def test_datetime_field_utc(self): | ||
class TestSerializer(serializers.Serializer): | ||
appointment = serializers.DateTimeField() | ||
peterthomassen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
appointment = datetime(2024, 12, 24, 0, 55, 30, 345678) | ||
serializer = TestSerializer(data={"appointment": appointment}) | ||
serializer.is_valid() | ||
renderer = HTMLFormRenderer() | ||
field = serializer['appointment'] | ||
rendered = renderer.render_field(field, {}) | ||
self.assertInHTML( | ||
'<input name="appointment" class="form-control" type="datetime-local" value="2024-12-24T00:55:30.345">', | ||
rendered | ||
) | ||
|
||
|
||
class TestHTMLFormRenderer(TestCase): | ||
def setUp(self): | ||
class TestSerializer(serializers.Serializer): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was harder than I thought!
Let me know if this is the correct way to get the datetime value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. Is it guaranteed that there is always a parent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a depth knowledge of the framework, but the only place I found where it can be
None
is:django-rest-framework/rest_framework/fields.py
Line 334 in 1472848
A DRF field can be outside of a seralizer?