everspader
everspader

Reputation: 1710

How to properly validate date field in Django forms?

I am very new to Django forms and I'm trying to make a very simple form to select a from and to dates to filter out some data. I don't wan't the to date to be later than today's date. I'm having a hard time understanding why when clean_to_date fails i.e., the to date is later than Today, the cleaned_data dict only has a from_data.

class DateSelect(forms.Form):
    from_date = forms.DateTimeField(
                    label='From:',
                    input_formats=['%d/%m/%Y'],
                    required=False)

    to_date = forms.DateTimeField(
                    label='To:', 
                    input_formats=['%d/%m/%Y'],
                    required=False)


    def clean_to_date(self):
        data = self.cleaned_data['to_date']

        if data != None and data > datetime.today():
            raise forms.ValidationError(
                    """
                    \'to\' date cannot be later than today.
                    """)

This is my piece of code in the html template so when I hit OK I just want it to refresh and display the filtered data.

<form action="/admin/report/latest-uploads/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="OK">
</form>

BTW, I have read already Django's documentation on Form and field validations but I'm still a bit confused.

views.py

def latest_uploads(request):
    
    if request.method == 'POST':
        form = DateSelect(request.POST)

        if form.is_valid():
            from_date = form.cleaned_data['from_date']
            to_date = form.cleaned_data['to_date']

            #some if function calls here

            context = {...
                       'from': form}
    
            return render(request, 'health_report/latest-uploads.html', context)

    else:
        form = DateSelect(request.GET)

        # function here

        context = {...,
                   'form': form}

        return render(request, 'health_report/latest-uploads.html', context)

Upvotes: 0

Views: 3922

Answers (1)

fannik
fannik

Reputation: 1153

In your example, you're checking for None but it is possible to make it required=True in the form definition. The very important in the cleaning process, that every def clean_() function needs to return a cleaned value or the same value (if it's OK).

Docs is here:

    # Always return a value to use as the new cleaned data, even if
    # this method didn't change it.

So back to your code:

def clean_to_date(self):
    data = self.cleaned_data['to_date']
    if data > timezone.now().date():
        raise forms.ValidationError("'to' date cannot be later than today.")
    return data

UPD: Also, you have to use Timezone instead of DateTime. from django.utils import timezone Check the code, with timezone.now().date() replacement.

Upvotes: 2

Related Questions