I have a view where I validate date and time on form submit making sure the date + time are not past. Date and Time are two separate fields. It works, but I know its wrong way of doing it and the date+time should be validated in Django Forms.
This is in my view.py
(Probably not done the right way but it works)
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:
...
now my goal is to have something like the above in Django forms:
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', ...]
Edit:
working code:
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
Thanks to all for the help especially xyres for his work and for being patient with me!
You are trying to validate over multiple fields. This point is well covered by the django documentation, see https://docs.djangoproject.com/en/1.7/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other.
The job has to be done in the
clean
method. Assuming django 1.7, your code could look likeI'll try to answer one last time. Instead of doing
def clean_my_date(...)
, do this:If the above solution doesn't work, try this answer.
Update
Since the above code worked, I feel I should try and explain why and how.
Let's look at the order of fields in your form
As, you can see
my_time
field comes aftermy_date
field. So, when your code was likethe
clean()
method of your form gets called and it returns a dictionary object calledcleaned_data
. Thiscleaned_data
dict has all the keys i.e. fields of your form uptomy_date
field. Any field that is aftermy_date
won't be incleaned_data
. As,my_time
field is aftermy_date
field, it was not incleaned_data
. That is why you got aKeyError
.After changing your code to
the
clean()
method returnedcleaned_data
with all the fields uptomy_time
. Asmy_date
comes beforemy_time
, it is, therefore, present incleaned_data
. Hence, no error.So it depends on the order of your form fields. If you want to validate two fields together, do it in the
clean_my_field(self)
method of the field that comes later in order. The answer posted by Jérôme Thiard is also a good alternative.