Open glennpierce opened 9 years ago
Same here, maybe this is an issue with different localizations / conversion between localizations?!
EDIT: Solution (?): Specify input format for the DateField:
deadline = forms.DateField(input_formats = ["%d.%m.%Y"], required = True, widget=DateWidget(usel10n=True, bootstrap_version=3,))
Now I specify the localized date format and it works for me. Is it possible to specify this automatically!?
I'm also having this problem. If I leave the widget format as the default, the day and month are swapped when saved, if I try to specify any sort of format in the widget, I get the error "Enter a valid date/time."
The datewidget simply passes a string (as given on the UI) to the DateField. The DateField first checks if it got a datetime.date(time), which is not the case. Then it tries to parse the string by testing different format specifiers. In my case the format specifier used by the datewidget was not defined in the DateField, so I defined this by hand (see above). What's not so nice is that you would need to specify a format for the DateField for each possible localization, this should somehow work automatically, e.g. if the datewidget did not pass a string but already a datetime.date object.
I assume that the swapping of day and month is because e.g. datewidget use "%d/%m/%Y" and DateField assumes "%m/%d/%Y".
In my case I only have one localization so it's ok for now.
The problem in init method of PickerWidgetMixin when language string converted to js objects. Init in django enviroment with following code
datestart = forms.DateTimeField(label=("Date Start"), widget=DateTimeWidget(usel10n=True, bootstrap_version=3), required=False)
called only once, when application loading, and not per request. Actually now, with example from documentation django-datetime-widget does not support locale changes per requests, you need to manually call widget initialization per request to change locale of widget and have true support of l18n. I think this is main problem of ValidationErrors on l18n-enabled sites.
Great catch, I suspect this is my fault from my opinionated refactor a while back. I moved some of the code into the __init__
as I clearly failed to realise some of the details might change from request to request. We should change that back.
This class works fine for me on l18n-enabled site.
class PickerWidgetMixin(object):
format_name = None
glyphicon = None
def __init__(self, attrs=None, options=None, usel10n=None, bootstrap_version=None):
if bootstrap_version in [2,3]:
self.bootstrap_version = bootstrap_version
else:
# default 2 to mantain support to old implemetation of django-datetime-widget
self.bootstrap_version = 2
if attrs is None:
attrs = {'readonly': ''}
self.options = options
self.format = None
self.usel10n = usel10n
if not usel10n and 'format' in self.options:
# We want to have a Javascript style date format specifier in the options dictionary and we
# want a Python style date format specifier as a member variable for parsing the date string
# from the form data
self.format = toPython_re.sub(
lambda x: dateConversiontoPython[x.group()],
self.options['format']
)
else:
self.format = None
super(PickerWidgetMixin, self).__init__(attrs, format=self.format)
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs)
rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs)
language = get_supported_language(get_language())
self.options['language'] = language
if self.usel10n or not self.format:
self.format = get_format(self.format_name)[0]
self.options['format'] = toJavascript_re.sub(
lambda x: dateConversiontoJavascript[x.group()],
self.format
)
#if not set, autoclose have to be true.
self.options.setdefault('autoclose', True)
# Build javascript options out of python dictionary
options_list = []
for key, value in iter(self.options.items()):
options_list.append("%s: %s" % (key, quote(key, value)))
js_options = ",\n".join(options_list)
# Use provided id or generate hex to avoid collisions in document
id = final_attrs.get('id', uuid.uuid4().hex)
clearBtn = quote('clearBtn', self.options.get('clearBtn', 'true')) == 'true'
return mark_safe(
BOOTSTRAP_INPUT_TEMPLATE[self.bootstrap_version]
% dict(
id=id,
rendered_widget=rendered_widget,
clear_button=CLEAR_BTN_TEMPLATE[self.bootstrap_version] if clearBtn else "",
glyphicon=self.glyphicon,
options=js_options
)
)
def _media(self):
js = ["js/bootstrap-datetimepicker.js"]
language = get_supported_language(get_language())
if language != 'en':
js.append("js/locales/bootstrap-datetimepicker.%s.js" % language)
return widgets.Media(
css={
'all': ('css/datetimepicker.css',)
},
js=js
)
media = property(_media)
While using DateTimeInput (default for admin) it actually splits the date and time fields as id_fieldName_0 as date field and id_fieldName_1 as time field. When this DateTimeWidget is used, the post data contains only fieldName as single value, when django expects list of values. Hence in django admin, DateTimeWidget will always throw ValidationError to send values as list. (Tested in Django 1.8 with l10n false in settings)
Is there a fix for this? I'm getting this error with a DateTimeField and looking at this comment thread I'm no closer to finding a fix.
Update: Seems the widget is adding apostrophes around the value e.g. "'2016-03-21 11:00:00'" which is causing the validation failure. Is there anyway to disable this?
Hi I have setup a form widget like
dt = forms.DateTimeField("Export start time", widget=DateTimeWidget(usel10n=True, bootstrap_version=3))
The format I chose in formats.py is chosen correctly. I can change the format and the widget changes when choosing a date. On submit though I always get "Enter a valid date/time."
Any suggestions ?
Thanks