我有一个视图,我在表单提交上验证日期和时间,确保日期+时间不会过去。日期和时间是两个单独的字段。它有效,但我知道它的错误方法,并且应该在Django Forms中验证日期+时间。
这是我的view.py
(可能没有采用正确的方法,但它有效)
my_date = request.session['reservationdate'] #in "mm/dd/yyyy" format
my_time = request.session['reservationtime'] #in "hh:mm" format
my_date_time = (my_date + ' ' + my_time + ':00') #convert to "mm/dd/yyyy hh:mm:ss"
my_date_time = datetime.strptime(my_date_time, '%m/%d/%Y %H:%M:%S') #convert to valid datetime
if datetime.now() <= my_date_time:
#do this
else:
...
现在我的目标是在Django表单中使用上述内容:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_date'].required = True
self.fields['my_time'].required = True
...
def clean_my_date(self):
my_date = self.cleaned_data['my_date']
my_time = self.cleaned_data['my_time']
my_date_time = (my_date + ' ' + my_time + ':00')
my_date_time = datetime.strptime(my_date_time, '%m/%d/%Y %H:%M:%S')
if datetime.now() <= my_date_time:
raise forms.ValidationError(u'Wrong Date!')
return my_date
class Meta:
model = MyModel
fields = ['my_date', 'my_time', ...]
修改
工作代码:
def clean_my_time(self):
my_date = self.cleaned_data['my_date']
my_time = self.cleaned_data['my_time']
my_date_time = ('%s %s' % (my_date, my_time))
my_date_time = datetime.strptime(my_date_time, '%Y-%m-%d %H:%M:%S')
if datetime.now() >= my_date_time:
raise forms.ValidationError(u'Wrong Date or Time! "%s"' % my_date_time)
return my_time
感谢所有人的帮助,特别是 xyres ,感谢他的工作和对我的耐心!
答案 0 :(得分:2)
您正在尝试验证多个字段。 django文档很好地介绍了这一点,请参阅https://docs.djangoproject.com/en/1.7/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other。
必须使用clean
方法完成工作。
假设django 1.7,你的代码看起来像
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_date'].required = True
self.fields['my_time'].required = True
...
def clean(self):
cleaned_data = super(MyForm, self).clean()
# here all fields have been validated individually,
# and so cleaned_data is fully populated
my_date = cleaned_data.get('my_date')
my_time = cleaned_data.get('my_time')
if my_date and my_time:
my_date_time = (my_date + ' ' + my_time + ':00')
my_date_time = datetime.strptime(my_date_time, '%m/%d/%Y %H:%M:%S')
if datetime.now() <= my_date_time:
msg = u"Wrong Date time !"
self.add_error('my_date', msg)
self.add_error('my_time', msg)
return cleaned_data
class Meta:
model = MyModel
fields = ['my_date', 'my_time', ...]
答案 1 :(得分:1)
我会尝试最后一次回答。不要执行def clean_my_date(...)
,而是执行此操作:
def clean_my_time(self):
# rest of your code remains same
如果上述解决方案不起作用,try this answer。
<强>更新强>
由于上述代码有效,我觉得我应该尝试解释原因和方法。
让我们看一下表单中字段的顺序
fields = ['my_date', 'my_time', ...]
您可以在 my_time
字段后看到my_date
字段。所以,当你的代码就像
def clean_my_date(self)
调用表单的clean()
方法,它返回一个名为cleaned_data
的字典对象。此cleaned_data
dict包含表单至 my_date
字段的所有键即字段。 my_date
之后的任何字段都不在cleaned_data
中。由于my_time
字段位于my_date
字段之后,因此不在cleaned_data
中。这就是你得到KeyError
的原因。
将代码更改为
def clean_my_time(self)
clean()
方法返回cleaned_data
所有字段最高 my_time
。由于my_date
位于my_time
之前,因此它出现在cleaned_data
中。因此,没有错误。
所以这取决于表单字段的顺序。如果要同时验证两个字段,请在稍后出现的字段的clean_my_field(self)
方法中执行此操作。 JérômeThiard发布的答案也是一个不错的选择。