Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Substituting an absent field value when saving a modelform

I have a this model:

class Fleet(models.Model):
    company     =   models.ForeignKey("Company", editable=False)
    aircraft    =   models.ForeignKey("Aircraft")
    size        =   models.IntegerField(default=1)
    description =   models.TextField(blank=True)

    def __unicode__(self):
        return u"%s" % (self.aircraft, )

And then a form based on this model:

class FleetForm(ModelForm):
    class Meta:
        model = Fleet
        exclude = ('company', )

When I use this form in a template, the "company" field is not added, which is expected. But that field is required as blank != True.

The way I use this form, the company attribute will always be known in the view function, as it's passed from the URL. How can I add the company to the form in the view function before I save it?

Here is my view:

def new_fleet(request, company_id):
    from forms import FleetForm

    company = Company.objects.get(pk=company_id)

    if request.method == "POST":
        form = FleetForm(request.POST,)

        form.company = company            #doesn't work

        form = form.save(commit=False)    #can't do this because the form 
        form.company = company            #doesn't validate (company is not set)

        if not form.errors:
            form.save()

    else:
        fleet = Fleet(company=company)    #pointless because the company widget
        form = FleetForm(instance=fleet)  #isn't created but eh whatever
like image 572
priestc Avatar asked Jun 06 '09 11:06

priestc


2 Answers

There are two ways to solve this issue:

Instantiate your model with initial values for the missing, but required fields:

company = Company.objects.get(pk=company_id)
fleet = Fleet(company=company)
form = FleetForm(request.POST, instance=fleet)
new_fleet = form.save()

Use save(commit=False) and manually set any extra required fields:

company = Company.objects.get(pk=company_id)
form = FleetForm(request.POST)
fleet = form.save(commit=False)
fleet.company = company
new_fleet = fleet.save()

See the note in this section of the ModelForm API documentation for more details.

By the way, either editable=False or exclude is enough to remove a field from a ModelForm; you don't need both.

like image 149
Ayman Hourieh Avatar answered Nov 10 '22 10:11

Ayman Hourieh


in @Ayman Hourieh 's answer . Just to address a pitfall in Django. If you have many-to-many field in the form. it would not get saved here. You should explicitly call save_m2m() . add one more line as below.

form.save_m2m()
like image 26
Ryu_hayabusa Avatar answered Nov 10 '22 08:11

Ryu_hayabusa