2013-02-01 59 views
3

我正在寻找最简单和最干净的方式来呈现具有3选择的基本DateField。如何使用3选择呈现DateField

<select>day</select><select>month</select><select>year</select> 

(如果可能的话使用“格式”选择如何显示最终渲染)

回答

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)) 
+0

如何访问模板中的单个日,月,年子域?提前致谢。 – gorus

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') 
+0

我还没有尝试过自己尚未但是你进去看了SelectMultip wtforms中的leField()字段? – codegeek

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()) 
+0

非常优雅的解决方案:)谢谢。 – yFy