Reputation: 11523
I have this view:
def new_booking(request):
if request.method == "POST":
form = BookingForm(request.POST, request.FILES)
print "form before clean: %s" % form.data # Data is here
if form.is_valid():
form.save()
and this form:
class BookingForm(forms.ModelForm):
def clean(self):
print "form data in clean method: %s" % self.cleaned_data
hora = self.cleaned_data['hora'] # !!! KeyError
print hora
class Meta:
model = Booking
fields = ['hora', 'nombre', 'email', 'archivo']
widgets = {
'nombre': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'archivo': forms.FileInput(attrs={}),
'hora': forms.TextInput(attrs={'class': 'form-control date', 'id': 'booking_time', 'readonly': 'readonly'})
}
So.. the first print (the one in the view) gives me this:
form before clean: <QueryDict: {u'hora': [u'Jueves 4 de Febrero a las 9:00 am '], u'nombre': [u'Alejandro'], u'csrfmiddlewaretoken': [u'**********'], u'email': [u'[email protected]']}>
The second print, the one in the clean
method, gives me this:
form data in clean method: {'nombre': u'Alejandro', 'email': u'[email protected]', 'archivo': <InMemoryUploadedFile: SO_username_admin_upZnsyk.png (image/png)>}
As you can see, for some reason I don't understand, the hora
kwarg has disappeared from the data dict: It doesn't show up in self.cleaned_data
.
Extra info: I need to manipulate it in the clean
method cause I'm receiving a string I need to coerce into a datetime. But, why isn't it there?
Upvotes: 0
Views: 3559
Reputation: 11523
Ok, the solution was to declare the field explicitly:
class BookingForm(forms.ModelForm):
hora = forms.CharField(max_length=150, required=True,
widget=forms.TextInput(attrs={'class': 'form-control date', 'id': 'booking_time', 'readonly': 'readonly'})) #HERE
def clean_hora(self):
hora = self.cleaned_data['hora']
return process_time_string(hora)
class Meta:
model = Booking
fields = ['hora', 'nombre', 'email', 'archivo']
widgets = {
'nombre': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'archivo': forms.FileInput(attrs={}),
'hora': forms.TextInput(attrs={'class': 'form-control date', 'id': 'booking_time', 'readonly': 'readonly'})
}
Then, I can receive the data in self.cleaned_data['hora']
and process it in the function clean_hora
as @LostMyGlasses suggested. The function process_time_string
just gets the string, calls strptime
and returns a datetime.
Upvotes: 0
Reputation: 3144
You declare 'hora' in your form as a TimeInput
, but the value you receive in request.POST
is a string that not only contains the time, but also the date. For that reason, the value is invalid and 'hora' is not set in form.cleaned_data
when the clean()
method is called. I guess form.is_valid()
returns false.
Upvotes: 1
Reputation: 25539
You need to call the base class clean method first to get the cleaned_data:
def clean(self):
cleaned_data = super(BookingForm, self).clean()
print "form data in clean method: %s" % cleaned_data
hora = self.cleaned_data['hora']
print hora
Django doc example of clean method.
Upvotes: 1