我正在寻找最简单,最干净的方法来渲染基本的DateField,并选择3。
<select>day</select><select>month</select><select>year</select>
(如果可能的话,使用“format”来选择如何显示最终渲染)
答案 0 :(得分:1)
您可以利用DateField处理多值输入并将它们与空格连接在一起这一事实,这样您就可以避免使用辅助表单而只是提供一系列输入:
from wtforms.widgets.core import Select, HTMLString, html_params
class SelectDateWidget(object):
FORMAT_CHOICES = {
'%d': [(x, str(x)) for x in range(1, 32)],
'%m': [(x, str(x)) for x in range(1, 13)],
'%y': [(x, str(x)) for x in range(1950, 2014)],
}
def __call__(self, field, **kwargs):
field_id = kwargs.pop('id', field.id)
html = []
for format in field.format.split():
choices = self.FORMAT_CHOICES[format]
id_suffix = format.replace('%', '-')
params = dict(kwargs, name=field.name, id=field_id + id_suffix)
html.append('<select %s>' % html_params(params))
if field.data:
current_value = int(field.data.strftime(format))
else:
current_value = None
for value, label in choices:
selected = (value == current_value)
html.append(Select.render_option(value, label, selected))
html.append('</select>')
return HTMLString(''.join(html))
# Usage
class MyForm(Form):
american_date = DateField(format='%m %d %y', widget=SelectDateWidget())
european_date = DateField(format='%d %m %y', widget=SelectDateWidget())
答案 1 :(得分:1)
最终小部件:(支持多种格式不仅是空格)
class SelectDateWidget(object):
FORMAT_CHOICES = {
'%d': [(x, str(x)) for x in range(1, 32)],
'%m': [(x, str(x)) for x in range(1, 13)]
}
FORMAT_CLASSES = {
'%d': 'select_date_day',
'%m': 'select_date_month',
'%Y': 'select_date_year'
}
def __init__(self, years=range(1930, 2014)):
super(SelectDateWidget, self).__init__()
self.FORMAT_CHOICES['%Y'] = [(x, str(x)) for x in years]
def __call__(self, field, **kwargs):
field_id = kwargs.pop('id', field.id)
html = []
allowed_format = ['%d', '%m', '%Y']
for format in field.format.split():
if (format in allowed_format):
choices = self.FORMAT_CHOICES[format]
id_suffix = format.replace('%', '-')
id_current = field_id + id_suffix
kwargs['class'] = self.FORMAT_CLASSES[format]
try: del kwargs['placeholder']
except: pass
html.append('<select %s>' % html_params(name=field.name, id=id_current, **kwargs))
if field.data:
current_value = int(field.data.strftime(format))
else:
current_value = None
for value, label in choices:
selected = (value == current_value)
html.append(Select.render_option(value, label, selected))
html.append('</select>')
else:
html.append(format)
html.append('<input type="hidden" value="'+format+'" %s></input>' % html_params(name=field.name, id=id_current, **kwargs))
html.append(' ')
return HTMLString(''.join(html))
答案 2 :(得分:0)
我使用了自定义小部件并且它正在运行,但它还不完美。其他想法吗?
class SelectDateWidget(object):
class SelectDateForm(Form):
days = [(x,x) for x in range(1,32)]
months = [(x,x) for x in range(1,13)]
years = [(x,x) for x in range(1950,2014)]
days_select = SelectField(choices=days)
month_select = SelectField(choices=months)
year_select = SelectField(choices=years)
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
date_form = self.SelectDateForm(prefix=field.name)
days_html = date_form.days_select(class_="input-mini").__html__()
month_html = date_form.month_select(class_="input-mini").__html__()
year_html = date_form.year_select(class_="input-small").__html__()
widget_html = field.format
widget_html = widget_html.replace('%d', days_html)
widget_html = widget_html.replace('%m', month_html)
widget_html = widget_html.replace('%Y', year_html)
return HTMLString(widget_html)
class SelectDateField(DateField):
widget = SelectDateWidget()
def __init__(self, label=None, validators=None, **kwargs):
super(SelectDateField, self).__init__(label, validators, **kwargs)
def pre_validate(self, extra):
form = SelectDateWidget.SelectDateForm(prefix=self.name)
try:
date = datetime.datetime.strptime(form.days_select.data+'-'+form.month_select.data+'-'+form.year_select.data, '%d-%m-%Y')
self.data = date
except:
raise StopValidation(gettext(u'Invalid date.'))
class MyForm(Form):
date = SelectDateField(u'Date', validators=[Required(message=_(u'This field is required.'))], format='%d / %m / %Y')