#3672 closed Uncategorized (fixed)
newforms: DateField doesn't handle date output formats
Reported by: | Owned by: | Adi J. Sieker | |
---|---|---|---|
Component: | Forms | Version: | dev |
Severity: | Normal | Keywords: | DateField l10n localization format input output |
Cc: | scott@…, gary.wilson@…, jesse.lovelace@…, ajs@…, blake@…, andy@…, tao_jonesin@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
As it stands, the when using a newforms.DateField with specified input
formats, it gets parsed alright, but when rendering the form there is
no way to specify the output format, it gets printed as YYYY-MM-DD.
By looking in the source code, I haven't been able to find anything related to this, so I think DateField needs some tweaking.
This not only is a bad localization practice, it makes _using_ the
input formats impossible, since when re-submitting a populated form
without changes, you get validation errors.
Since we can define multiple input formats, but there is only one output format (obviously), I suggest:
a) Defining a new parameter, output_format
b) Make it optional, and set it to the first input format defined in the form field.
Attachments (6)
Change History (29)
comment:1 by , 18 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:2 by , 18 years ago
Cc: | added |
---|
by , 18 years ago
Attachment: | date-time-formatting-widgets.py added |
---|
Widgets that format date or time before rendering
comment:3 by , 18 years ago
I ran into this today.
For me it would be enough to make the field render its content according to input_formats
parameter.
But as said, this bug indeed leaves the DateField unusable for now :(
comment:4 by , 18 years ago
Whipped up a quick workaround:
First, make timeformat variable
from datetime import date TIME_FORMAT = '%d.%m.%Y'
then use it in input_formats
date_of_birth = forms.DateField(input_formats=[TIME_FORMAT], label="Date of Birth", required=False, help_text="Format like 17.12.1979")
and when initializing the form, use strftime
date_of_birth = user.get_profile().date_of_birth form = MyForm(initial={'date_of_birth': date_of_birth.strftime(TIME_FORMAT)})
Not very DRY or pretty, but it seems to work.
comment:5 by , 18 years ago
Cc: | added |
---|
by , 18 years ago
Attachment: | date-time-formatting-widgets.2.py added |
---|
Bug fix: If an invalid date or time is entered the widgets don't try to format it
comment:6 by , 18 years ago
Cc: | added |
---|
comment:8 by , 17 years ago
Has patch: | set |
---|---|
Needs tests: | set |
Patch needs improvement: | set |
Triage Stage: | Design decision needed → Accepted |
I'm leaning towards the patch attached to this ticket rather than the one on #3533 since the one here splits the Date and Time widgets and makes use of formats in settings.py
.
How about some tests and a patch in diff format.
by , 17 years ago
Attachment: | date-time-widgets-tests.diff added |
---|
Widgets (slightly remodeled) and tests as a diff
comment:9 by , 17 years ago
Note that these widgets take a Django style format string like 'N j, Y' versus Python strftime() style like '%b %d, %Y'.
It means you could have a field definition with two different styles of date format strings like:
class MyForm(forms.Form): start_date = forms.DateField(widget=DateTextInput(format='d/m/y'), input_formats=('%d/%m/%y',))
However, I think it makes sense to use Django format strings for output since it is used elsewhere in the UI and is perhaps more powerful. DateField uses strftime() patterns for input, but it is parsing using strptime() so that's the natural format.
comment:10 by , 17 years ago
Found this incredibly useful. Have implemented a modified version that uses datetime.strftime and it is working perfectly for me. However, I'm surprised this has been open for 1 year and has not made yet it into trunk.
by , 16 years ago
Attachment: | date-time-widgets-tests-2.diff added |
---|
updated to work with trunk and use translated DATE_FORMAT and TIME_FORMAT as well
comment:11 by , 16 years ago
Cc: | added |
---|
new patch now works with trunk.
I also changed how the date and time formats are determined.
- user supplied
- format from translation using ugettext
- format from settings.
I also tried to add the new text inputs as default widgets to the DateField and TimeField model fields.
This breaks forms tests and modelforms tests, since the tests supply unicode strings instead of datetime.date or datetime objects to the date and time widgets. The new widgets return None if they are not supplied with a datetime.date or datetime.datetime instances.
Now my question is: Does a widgets have to handle unicode strings (thinking about POST or GET values) or do the widgets always get value from to_python?
Actually thinking about it some more having to handle unicode is probably a must since I can use a Form without a Model.
So I'd leave unicode strings as they are and only format date and datetime instance. Is that OK?
by , 16 years ago
Attachment: | date-time-widgets-tests-7601.diff added |
---|
update the patch again, removed the usage for DATE_FORMAT from the translation.
comment:12 by , 16 years ago
Owner: | changed from | to
---|
the usage of DATE_FORMAT from the translation or utils.translation.get_date_format doesn't actually make much sense for input control. The german DATE_FORMAT is 12. Apr 2008 which, when displayed in an input control doesn't feel correct.
comment:13 by , 16 years ago
Cc: | added |
---|
comment:14 by , 16 years ago
Thanks for the patches. I am new to Python and Django can't really understand how all that works.
Here the solution for DateField that I am using; it doesn't rely on settings.DATE_FORMAT but on the field input_formats property:
from django import newforms as forms from django.newforms.fields import DEFAULT_DATE_INPUT_FORMATS import datetime DEFAULT_DATE_OUTPUT_FORMATS = DEFAULT_DATE_INPUT_FORMATS[0] class FormattedTextInput(forms.widgets.TextInput): "Overrides TextInput to render formatted value." def render(self, name, value, attrs=None): formatted_value = None if value: formatted_value = self.format_value(value) return super(FormattedTextInput, self).render(name, formatted_value, attrs) class DateFormattedTextInput(FormattedTextInput): "Renders formatted date." def __init__(self, format=None, attrs=None): super(DateFormattedTextInput, self).__init__(attrs) self.format = format or DEFAULT_DATE_OUTPUT_FORMATS def format_value(self, value): if isinstance(value, datetime.date) or isinstance(value, datetime.datetime): return value.strftime(self.format) else: return value class DateField(forms.DateField): widget = DateFormattedTextInput def __init__(self, *args, **kwargs): super(DateField, self).__init__(*args, **kwargs) self.widget.format = self.input_formats[0]
Hope it helps.
comment:15 by , 16 years ago
Needs tests: | unset |
---|---|
Patch needs improvement: | unset |
DateTimeField's widget (DateTimeInput) already allows to format date and datetime object.
comment:16 by , 16 years ago
Cc: | added |
---|
follow-up: 21 comment:17 by , 16 years ago
milestone: | → post-1.0 |
---|
Hello
i think
def format_value(self, value):
if isinstance(value, datetime.date) or isinstance(value, datetime.datetime):
return value.strftime(self.format)
else:
return value
needs to be changed to:
def format_value(self, value):
if isinstance(value, datetime.date) or isinstance(value, datetime.datetime):
try:
return value.strftime(self.format)
except:
return value
else:
return value
Otherwise the value.strftime(self.format) would crash the form (form render returns "") if the field-value does not validate on calling form.is_valid()
If my approach is wrong please let me know. I'm very new to django/python :)
comment:19 by , 16 years ago
Cc: | added |
---|
comment:20 by , 16 years ago
Cc: | added |
---|
comment:21 by , 15 years ago
Patch needs improvement: | set |
---|
No response to marxis.rene@googlemail.com yet so marking as patch needs improvement until somebody responds to that issue. Comment 15 marks this as not even relevant anymore - not sure either way.
comment:22 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I think these needs were fulfilled with the changes introduced in r11964 (GSoC 2010 project) and further refinements committed later since then.
comment:23 by , 13 years ago
Cc: | removed |
---|---|
Easy pickings: | unset |
Severity: | → Normal |
Type: | → Uncategorized |
UI/UX: | unset |
I ran in to the same problem today. Seems like maybe this is a job for the widget, rather than the field? My interim solution was to write widgets that derive from TextInput, override render and format the value before it is written out. Code for the widgets is attached.