4

I need to override the clean() method of my Django form to test two datefields together: a begin_date and a end_date (is the end date posterior to start date, and is the begin date posterior to now).

The problem is that when one of these two fields is empty or invalid, I got an exception (KeyError). I'd like to got a simple error form like I got with empty charfields.

I was pretty sure to find the answer here: Django self.cleaned_data Keyerror but I didn't.

Here is the code:

class MyForm(forms.Form):
    begin_date = forms.DateField()
    end_date = forms.DateField()
    #...

    def clean(self):

        cleaned_data = super(MyForm, self).clean()
        errors = []

        begin_date = cleaned_data['begin_date']
        end_date = cleaned_data['end_date']
        #...

        # Test 1
            if begin_date < date.today():
                errors.append(forms.ValidationError(
                "La date de début doit être postérieure à la date actuelle"))
        # Test 2
            if end_date < begin_date:
                errors.append(forms.ValidationError(
                "La date de fin doit être posétieure à la date de début"))

        if errors:
            raise forms.ValidationError(errors)

        return cleaned_data
Community
  • 1
  • 1
David Dahan
  • 10,576
  • 11
  • 64
  • 137

2 Answers2

3

In Django, when you call the super(MyForm, self).clean() the superclass fill the cleaned_data ONLY if the data is already valid this is why in the docs are using the get method (https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other).

As you wan't to compare datetime object together, use this code to ensure date fields are correct:

if 'begin_date' in cleaned_data.keys():
        begin_date = cleaned_data['begin_date']
    else:
        begin_date = None
        errors.append(forms.ValidationError(
            "Bad start date format or empty"))
David Dahan
  • 10,576
  • 11
  • 64
  • 137
soloidx
  • 729
  • 6
  • 12
  • I saw this on another post too. But the problem is `cleaned_data.get('begin_date')` returns a string (not a date), and then I'm unable to do things like `begin_date < date.today()` – David Dahan May 27 '14 at 23:38
  • 2
    In that case you can try asking first if the key exist `if 'begin_date' in cleaned_data.keys():` after use a `cleaned_data['begin_date']` of try to convert the string to datetime but I'm sure the cleaned_data returns datetime objects – soloidx May 27 '14 at 23:45
  • Thanks a lot, this is exactly what I needed. Let me edit your answer to add the code and I'll mark it as accepted. Thanks again. – David Dahan May 28 '14 at 00:05
2

How about

if all([d in cleaned_data for d in ['begin_date', 'end_date']]):
    # your code
else:
    raise forms.ValidationError("A start date and end date are required")

This checks for the existence of both values before trying to use them, and if one or both are missing returns a suitable error message.

user3681414
  • 109
  • 1
  • 3