3

I have the following Django modelform. My form is for entering in times on a timesheet, and there are start_time and end_time fields. I want to add a custom check to make sure that the start_time is before, or less than, the end_time, or else if not provide some feed back to the user if it isn't. I'm trying to create a custom clean method to do that, but i'm doing something wrong.

(snippet from models.py)

class TimesheetEntry(Model):
    WORKED='worked'
    SICK='sick'
    VACATION='vacation'
    TIME_CHOICES=(
        (WORKED,'Worked'),
        (SICK,'Sick'),
        (VACATION,'Vacation'))

    timesheet = models.ForeignKey('Timesheet', related_name='entries')
    start_time = models.DateTimeField(default=datetime.datetime.now)
    end_time = models.DateTimeField(blank=True, null=True)

(snippet from forms.py)

class TimesheetEntryForm(forms.ModelForm):
    start_time = forms.DateTimeField(widget=forms.SplitDateTimeWidget())
    end_time = forms.DateTimeField(widget=forms.SplitDateTimeWidget())
    class Meta:
        model = TimesheetEntry
        exclude = ['timesheet']

    def clean(self, *args, **kwargs):
        super(TimesheetEntryForm, self).clean(*args, **kwargs)
        if self.fields['start_time'] >= self.fields['end_time']:
            raise ValidationError("Start Time should be less than End Time")

When I submit the form(whether the start_time is less than or greater than the end_time, i strangely get one of two errors with no apparent reason why it doesn't give me the same one each time. It does not update the db, and i can repeatedly try submitting the same form with the same data over and over and will give me one of the following two errors with approximately 50% probability as to which one. I know this is a small piece of a big puzzle, but I'm hoping someone can spot an obvious error i'm making and help me figure out how to correct this.

TypeError: argument of type 'NoneType' is not iterable

-OR-

NameError: global name 'ValidationError' is not defined

it should be noted that by removing the clean() method from the method will stop the errors and allow me to input new entries(including those resulting in a negative hours total-which is the end problem i'm trying to solve)

1
  • Have you imported the class ? from django.core.exceptions import ValidationError Commented Nov 8, 2014 at 22:03

2 Answers 2

1

Regarding the NameError, simply:

from django.core.exceptions import ValidationError

One more note, instead of rewriting form fields, do the following within the form's Meta:

widgets = {
           'start_time': SplitDateTimeWidget(),
           'end_time': SplitDateTimeWidget(),
          }

Lastly, clean method should look something like this:

def clean(self):
    cleaned_data = super(TimesheetEntryForm, self).clean()
    if cleaned_data.get('start_time') >= cleaned_data.get('end_time'):
        raise ValidationError("blah blah")

Hope it helps!

Sign up to request clarification or add additional context in comments.

Comments

0

Two errors: firstly, you should access self.cleaned_data['start_time'] (and end_time); and second, you need to reference forms.ValidationError.

Also, it won't hurt to do it but there is no actual need to call the super clean method.

5 Comments

Thanks Daniel, that solved the validation error, thanks for that. However now I just get the type error. It seems to be just calling the clean method, even if I take out everything else and just put in "pass" it is still giving me the same TypeError as before.
Here's a bit of the traceback if it provides any clues: File "/home/josh/.virtualenvs/fizbug/lib/python2.7/site-packages/django/forms/forms.py", line 275, in full_clean self._post_clean() File "/home/josh/.virtualenvs/fizbug/lib/python2.7/site-packages/django/forms/models.py", line 396, in _post_clean self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude) File "/home/josh/.virtualenvs/fizbug/lib/python2.7/site-packages/django/forms/models.py", line 46, in construct_instance or not f.name in cleaned_data: TypeError: argument of type 'NoneType' is not iterable
If you're not on Django 1.6, you need to return the cleaned_data dict.
Daniel, it's Django 1.6.7. Adding "return self.cleaned_data" at the bottom of the clean() method does actually eliminate the errors, and the logic does appear to be working in that it will only update the database if the entry passes the logic (start_time being less than end_time). So thanks for that tip! However, in case of error, it just returns the screen as though nothing happened. Any clue as to how to get an error message to display in the browser?
That depends on your view and your template. You should be following the pattern shown in the documentation (or use a generic view).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.