django的form将界面的展示和数据校验转换做了很好的封装,并且提供了很多的一些Field和Widget,昨天在做一个项目时有一个月报表的功能,查询的时候需要选择某年某月,于是参照一些网站信息,写了一个YearMonthField.
#创建年月表单控件
class YearMonthWidget(forms.MultiWidget):
"""
A widget that splits a date into Month/Year with selects.
"""
def __init__(self, attrs=None,year_range=None,month_range=None):
YEARS = year_range or range(2000,2021)
MONTHES = month_range or range(1,13)
years = map(lambda x: (x,x), YEARS )
months = map(lambda x:(x,x>9 and x or '0'+str(x)), MONTHES )
widgets = (forms.Select(attrs=attrs, choices=years),forms.Select(attrs=attrs, choices=months))
super(YearMonthWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return [value.year, value.month]
return [None, None]
class YearMonthField(forms.MultiValueField):
widget=YearMonthWidget
def __init__(self,*args,**kwargs):
fields = (
forms.IntegerField( required=True),
forms.IntegerField( required=True),
)
super(YearMonthField, self).__init__(fields, *args,**kwargs )
def compress(self, data_list):
if data_list:
return datetime.date(year=int(data_list[0]), month=int(data_list[1]), day=1)
return datetime.date.today()
代码说明:
主要是继承MultiWidget和MultiValueField
关键是分别有两个方法需要重写,decompress和compress.
widget中需要将数据解压缩成list和其中的widgets对应.
field中需要将list转成所需要的数据格式,如YearMonthField的datetime类型.
使用如下:
import datetime
class ReportMonthForm(Form):
month = YearMonthField(label='查询月份',initial=datetime.date.today())
界面如下: