[Solved]-Add fields to Django ModelForm that aren't in the model

1👍

  1. If I were you, I would have used the customised Django-admin date/time widget(s) for entering date/time entries.

  2. Regarding form validation, make sure you pass the form associated with the request for it to show up form-based errors. (Sample code below)

  3. As for using inheritance, it would be a overkill for this use-case as it will not serve any purpose and it would be better to keep things simple.

Sample code:

if request.POST:
    form = MyScheduleForm(request.POST)
    if form.is_valid():
        # Specific stuff with the variables here
        pass
else:
    form = MyScheduleForm()

1👍

Ok, I think I figured it out:

As of Django 1.2, running is_valid() triggers MODEL validation on ModelForms. I had assumed that fields would be checked for blank values BEFORE hitting the model clean() function, so my clean function doesn’t check for blank values or None types. Basically, my clean() in my model looks something like:

def clean(self):
  if self.start_datetime >  datetime.now():
        raise ValidationError('Start date can\'t be in the future')

So I suppose that mostly answer my question. However, I have 1 remaining question:

Is it best to check for blank values in the model clean(), or is there a better way to do this? Seems hackish to check for blanks in the model instead of in the ModelForm — is the validation on the form field supposed to flag missing inputs on required fields?

Thanks for everyone’s help.

👤Cyclic

0👍

1: I don’t think it’s wrong, because you have some very specific stuff going on there:

  • Specific time entries (noon, ending at 5PM..)
  • 15 minute increments for startminutes

2: Update: comment below says your field should be required=True by default. It’s true, you should be getting a ValidationError with your form if the field is left blank.

Can you post the TypeError you’re speaking about? Is it happening outside the clean() block? Because if you don’t return cleaned_data from your clean function like in your example, your form won’t have any data to work with even if it initially checks out by not raising any ValidationErrors.

Anyways, you can explore the clean_ methods for per field validation.

def clean_startdate(self):  
    if not self.cleaned_data['startdate']:
            raise forms.ValidationError("Must enter a start date")

http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method

3: Can you clarify here what you’re trying to do with inheritance? It looks like your field definitions are very specific to this form, so it belongs right here in the MyScheduleForm. Inheritance is for re-using code : )

If you are looking to reuse this for multiple DateTimeFields, yes you can use form inheritance. You could define a ModelForm like you have now, subclass it, and override the parent’s Meta as shown here in the docs to use it on multiple models:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance

I’d also check out how the django does its SplitDateTimeWidget (check the source):
http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.SplitDateTimeWidget

There are some other ‘3rd party’ split date time widgets worth taking a look at on the interwebs too!

0👍

For form fields that may contain blank values, you must declare the field as follows:

start_datetime=models.DateTimeField(blank=True, null=True)

This tells the form that it can be blank, and that the database field can be null. That may fix that problem.

Why are you using a ModelForm if you’re trying to include fields that are not a part of the Model? ModelForms are designed to quickly create forms that bind directly to your model. Of course they have various customizations, but changing the actual fields seems to me something that a regular Form is for.

Otherwise, if you just want to split the VIEW of the formm, not the form itself, create a custom widget to display the DateTime field, such as the SplitDateTimeWidget. Subclass it, and provide your CHOICES for the values of the drop down.

Leave a comment