Django验证日期&表格时间

时间:2014-12-18 17:55:19

标签: python django forms validation

我有一个视图,我在表单提交上验证日期和时间,确保日期+时间不会过去。日期和时间是两个单独的字段。它有效,但我知道它的错误方法,并且应该在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 ,感谢他的工作和对我的耐心!

2 个答案:

答案 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发布的答案也是一个不错的选择。