2
votes

I am trying to create a reservation form that creates an object for model Reservation when the form is posted. I am using a custom datepicker widget to pick the ate, but I am also using ModelForms.

The issue is that, if I do not have 'date' listed in the meta fields list in the forms.py, then the form doesn't look for the date field form input on post. But if I include 'date' inside the meta fields of the forms.py Modelform, then it errors and says "date field can not be left blank" even though it is not blank...

forms.py

class ReservationForm(forms.ModelForm):

    date = forms.DateField(
        widget=DatePickerInput(format='%m/%d/%Y')
        )
    def clean_date(self):
        data = self.cleaned_data['date']

        # Check if a date is not in the past.
        if data < datetime.date.today():
            raise ValidationError(_('Invalid date - reservation in past'), code='invalid')
            messages.danger(request, "Reservation Created")
            print('ERROR')


            # Remember to always return the cleaned date.
            return data

    class Meta:
        model = Reservation
        fields = ('reservation_time', 'people', 'name', 'email', 'phone') # REMOVED 'date'

views.py

def reservationFormView(request):
    #reservation = create(Reservation)
        # If this is a POST request then process the Form data
    if request.method == 'POST':
        # Create a form instance and populate it with data from the request (binding):
        form = ReservationForm(request.POST)

        # Check if the form is valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required

            reservation = form.save(commit=False)
            reservation.ReservationEmail = form.cleaned_data['email']
            reservation.ReservationName = form.cleaned_data['name']
            reservation.ReservationPeople = form.cleaned_data['people']
            reservation.ReservationTime = form.cleaned_data['reservation_time']
            reservation.date = form.cleaned_data['date']
            print( reservation.date)
            #reservation.created_time = timezone.now()
            reservation.save()

                # redirect to a new URL:
            return HttpResponseRedirect('/reservation-confirmation/')

        # If this is a GET (or any other method) create the default form.
    else:
        form = ReservationForm()

    return render(request, 'home/reservation_form.html', {'form': form, })

models.py

class Reservation(BaseModel):
    class Meta:
        verbose_name_plural = "Reservations"

    TIME_CHOICES = (
...
    )
    SEATING_CHOICES = (
...
    )
    date = models.DateField(null=True)
    name = models.CharField(max_length=35, null=True)
    phone = PhoneNumberField(null=True)   #USE THIS https://github.com/stefanfoulis/django-phonenumber-field
    email = models.EmailField(null=True)
    people = models.PositiveSmallIntegerField(choices=SEATING_CHOICES, default=None, db_index=True)
    reservation_time = models.PositiveSmallIntegerField(choices=TIME_CHOICES, default=None, db_index=True)

    def __str__(self):
        return '(%s) %s %s' % (self.date, self.name, self.phone )
1
You wrote return data in the body of the if part, not at the end of the method. - Willem Van Onsem
Thank you for the input, you are correct, that solved the issue. - Dominic M.
no the indentation is too much. If you look at the documentation you refer to, the return ... is indented under the def clean_date, not the if. - Willem Van Onsem
I edited the reply, thank you! - Dominic M.

1 Answers

2
votes

Your clean_date method does not return a value in case the if condition is False. You should return the cleaned data in case it is correct, like:

def clean_date(self):
    data = self.cleaned_data['date']

    # Check if a date is not in the past.
    if data < datetime.date.today():
        raise ValidationError(_('Invalid date - reservation in past'), code='invalid')
        messages.danger(request, "Reservation Created")

    # not indented under the if
    return data

Otherwise, this function will return None in case the data is valid, and raise a ValidationError in case the data is invalid.