Pol Frances
Pol Frances

Reputation: 402

Django populate form using Function based view with multiple forms

I'm using Django 2.1 with python 3.6 and postgreSQL.

I have to display 3 different forms in the same template. So I created a view in which I putted the 3 forms, but this doesn't show them populated as if using a CBV with generic.UpdateView.

I need to add the current information of the models that are being updated inside each form field.

I also created this because I didn't found a lot of information about how to create a FBV with multiple forms in Django. I imagine that there are few things that are not correct in the view, so all suggestions are welcome.

The view:

def project_update_view(request, pk):
    project = Project.objects.get(pk=pk)

    if request.method == 'POST':
        general_form = UpdateProjectGeneralForm(request.POST)
        investment_form = UpdateProjectInvestorDetailsForm(request.POST)
        create_job_form = UpdateProjectAddWorkersForm(request.POST)

        if general_form.is_valid():
            general_form.instance.user = request.user
            general_form.instance.history_change_reason = 'Project Updated'
            general_form.save()
            messages.success(request, 'Project updated!')
            return HttpResponseRedirect(request.path_info)

        if investment_form.is_valid():
            investment_form.instance.user = request.user
            investment_form.instance.history_change_reason = 'Investor Details Updated'
            investment_form.save()
            messages.success(request, 'Investment details updated!')
            return HttpResponseRedirect(request.path_info)

        if create_job_form.is_valid():
            create_job_form.instance.project = project
            create_job_form.instance.history_change_reason = 'New Job Added'
            create_job_form.save()
            messages.success(request, 'Job created!')
            return HttpResponseRedirect(request.path_info)

    else:
        general_form = UpdateProjectGeneralForm()
        investment_form = UpdateProjectInvestorDetailsForm()
        create_job_form = UpdateProjectAddWorkersForm()

    return render(request, 'webplatform/project_edit.html', {
        'general_form': general_form,
        'investment_form': investment_form,
        'create_job_form': create_job_form,
        'project': project,
    })

The forms: (To evade extra code, I just put one form. The others have the same structure)

class UpdateProjectInvestorDetailsForm(forms.ModelForm):
    class Meta:
        model = Project
        fields = ('investor_details', 'investment_percentage', 'investment_amount')
        widgets = {
            'investor_details': SummernoteWidget(attrs={'summernote': {
                'placeholder': 'Add some details for the future investors here...'}}),
        }

    def __init__(self, *args, **kwargs):
        # first call parent's constructor
        super(UpdateProjectInvestorDetailsForm, self).__init__(*args, **kwargs)
        # there's a `fields` property now
        self.fields['investment_amount'].required = True
        self.fields['investment_percentage'].required = True
        self.fields['investor_details'].required = True

The template: (this is one of the forms, but all of them follow the same structure)

<form method="post" enctype="multipart/form-data" novalidate>
    {% csrf_token %}
    <div class="row">
        <div class="col-6">
            {{ investment_form.investment_amount|as_crispy_field }}
        </div>
        <div class="col-6">
            {{ investment_form.investment_percentage|as_crispy_field }}
        </div>
        <div class="col-12">
            {{ investment_form.investor_details|as_crispy_field }}
        </div>

    </div>
    <button type="submit" name="investment_form" class="btn btn-primary">Update investment details
    </button>
</form>

Upvotes: 2

Views: 3534

Answers (1)

Pol Frances
Pol Frances

Reputation: 402

As @mfackowiak said on the comments, the problem is that my forms are not instanced with the model I want to edit, so I just had to change this:

general_form = UpdateProjectGeneralForm(request.POST)
investment_form = UpdateProjectInvestorDetailsForm(request.POST)
create_job_form = UpdateProjectAddWorkersForm(request.POST)

for this:

general_form = UpdateProjectGeneralForm(request.POST, instance=project)
investment_form = UpdateProjectInvestorDetailsForm(request.POST, instance=project)
create_job_form = UpdateProjectAddWorkersForm(request.POST)

As an extra, I saw that I can call the object with a get_object_or_404 so I use it on the first line and from this:

 project = Project.objects.get(pk=pk)

I got this:

 project = get_object_or_404(Project, pk=pk)

Upvotes: 3

Related Questions