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())
界面如下: