One html form, several interrelated django forms -

2019-07-22 03:23发布

问题:

There is a problem, I need to submit two interrelated modelforms with one html form. I know how to submit two separate forms, but foreign key makes me crazy in case of related modelforms.

The problem is, that second form should have filled field with foreign key to instance from first form.

In this particular case I decided to merge two models, but I think, there should be cases, where workaround for described problem would be useful.

Please consider following code:

Models:

from django.db import models

class Facility(models.Model):
    name = models.CharField(max_length=255)

class FacilityDetail(models.Model):
    some_details = models.CharField(max_length=255)
    facility = models.ForeignKey(Facility)

Corresponding django forms:

from django import forms

class FacilityForm(forms.ModelForm):

    class Meta:
        model = Facility
        fields = ('name')

class FacilityDetailForm(forms.ModelForm):

    class Meta:
        model = FacilityDetail
        fields = ('some_details', 'facility')

View to handle forms:

from django.views.generic import View

FACILITY_PREFIX = 'facility'
FACILITY_DETAIL_PREFIX = 'facility_detail'

class FacilityCreateView(View):

    def get(self, request, *args, **kwargs):
        facility_form = FacilityForm(prefix=FACILITY_PREFIX)
        facility_detail_form = FacilityDetailForm(prefix=FACILITY_DETAIL_PREFIX)

        context = {
            'facility_form': facility_form,
            'facility_detail_form': facility_detail_form,
        }

        return render(request, 'facility_create.html', context)

    def post(self, request, *args, **kwargs):
        facility_form = FacilityForm(request.POST, prefix=FACILITY_PREFIX)
        facility_detail_form = FacilityDetailForm(request.POST, prefix=FACILITY_DETAIL_PREFIX)

        if facility_form.is_valid():
            facility = facility_form.save()

            # is not valid, because there is no `facility`
            if facility_detail_form.is_valid():
                facility_detail_form.cleaned_data['facility'] = facility

                facility_detail_form.save()

                return redirect(...)

        context = {
            'facility_form': facility_form,
            'facility_detail_form': facility_detail_form,
        }

        return render(response, 'facility_list.html', context)

How should I handle form validation and saving in FacilityCreateView.post?

回答1:

One way you could fix this is:

facility_detail_form.cleaned_data['facility'] = facility

could be replaced with:

facility_detail = facility_detail_form.save(commit=False)
facility_detail.facility = facility
facility_detail.save()

#rest of the code.. .

Here commit=False creates the object for you, without saving it to the database, where you can assign your foreign key object before saving.