Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add fields to Django ModelForm that aren't in the model

I have a model that looks like:

class MySchedule(models.Model):
  start_datetime=models.DateTimeField()
  name=models.CharField('Name',max_length=75)

With it comes its ModelForm:

class MyScheduleForm(forms.ModelForm):
  startdate=forms.DateField()
  starthour=forms.ChoiceField(choices=((6,"6am"),(7,"7am"),(8,"8am"),(9,"9am"),(10,"10am"),(11,"11am"),
      (12,"noon"),(13,"1pm"),(14,"2pm"),(15,"3pm"),(16,"4pm"),(17,"5pm"),
      (18,"6pm"
  startminute=forms.ChoiceField(choices=((0,":00"),(15,":15"),(30,":30"),(45,":45")))),(19,"7pm"),(20,"8pm"),(21,"9pm"),(22,"10pm"),(23,"11pm")))

  class Meta:
    model=MySchedule

  def clean(self):
    starttime=time(int(self.cleaned_data.get('starthour')),int(self.cleaned_data.get('startminute')))
    return self.cleaned_data

  try:
    self.instance.start_datetime=datetime.combine(self.cleaned_data.get("startdate"),starttime)

  except TypeError:
    raise forms.ValidationError("There's a problem with your start or end date")

Basically, I'm trying to break the DateTime field in the model into 3 more easily usable form fields -- a date picker, an hour dropdown, and a minute dropdown. Then, once I've gotten the three inputs, I reassemble them into a DateTime and save it to the model.

A few questions:

1) Is this totally the wrong way to go about doing it? I don't want to create fields in the model for hours, minutes, etc, since that's all basically just intermediary data, so I'd like a way to break the DateTime field into sub-fields.

2) The difficulty I'm running into is when the startdate field is blank -- it seems like it never gets checked for non-blankness, and just ends up throwing up a TypeError later when the program expects a date and gets None. Where does Django check for blank inputs, and raise the error that eventually goes back to the form? Is this my responsibility? If so, how do I do it, since it doesn't evaluate clean_startdate() since startdate isn't in the model.

3) Is there some better way to do this with inheritance? Perhaps inherit the MyScheduleForm in BetterScheduleForm and add the fields there? How would I do this? (I've been playing around with it for over an hours and can't seem to get it)

Thanks!

[Edit:] Left off the return self.cleaned_data -- lost it in the copy/paste originally

like image 832
Cyclic Avatar asked Jan 12 '11 05:01

Cyclic


People also ask

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.


2 Answers

  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()
like image 68
sidhshar Avatar answered Oct 25 '22 23:10

sidhshar


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.

like image 24
Cyclic Avatar answered Oct 25 '22 23:10

Cyclic