Reputation: 402
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
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