Reputation:
I am trying take 2 different forms in one page in my Django project.
They have different form models but they are in the same page and use the same view function.
When I try them both of them works, but when I post one of them, the other one is also saving as a empty form. But I do not want this.
Why this is happening?
views.py
def ocr(request, id):
...
pdf = get_object_or_404(Pdf, id=id)
approval = ApprovalProcess(user_id=request.user, highest_rank=1)
#FORM 1
if request.method == 'POST':
form = PdfRiskForm(request.POST, request.FILES, instance=pdf)
if form.is_valid():
form.save()
if pdf.risk_rating == "Low Risk":
n = len([x for x in doa_low_list if x < pdf.credit_limit])
approval.highest_rank = n
elif pdf.risk_rating == "Medium Risk":
n = len([x for x in doa_medium_list if x < pdf.credit_limit])
....
approval.save()
else:
form = PdfRiskForm()
#FORM 2
if request.method == 'POST':
form_2 = CommentForm(request.POST or None)
if form_2.is_valid():
form_2.instance.comment_other = form.cleaned_data.get("comment_other")
form_2.instance.username = request.user
form_2.instance.comp_name = userP[0].company
form_2.instance.doc_id = pdf
if form_2.comment_others is not None:
form_2.save()
else:
form_2 = CommentForm()
models.py
class PdfRiskForm(forms.ModelForm):
risk_rating = forms.ChoiceField(label='Risk Rating', choices=Pdf.RISK_RATING)
credit_limit = forms.IntegerField()
comments = RichTextField
letter_portion = forms.IntegerField(min_value=0, max_value=100, required=False, label="Guarantee Portion (%)")
class Meta:
model = Pdf
fields = ['risk_rating', 'credit_limit', 'letter_portion', 'comments']
class CommentFromOthers(models.Model):
comp_name = models.ForeignKey(CompanyProfile, on_delete=models.CASCADE, null=True)
doc_id = models.ForeignKey(Pdf, on_delete=models.DO_NOTHING, null=True)
comment_others = RichTextField(blank=True)
created_date = models.DateTimeField(default=datetime.now())
username = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
template.html
<div class="card-body">
<form method="POST" enctype="multipart/form-data">
<!-- Very Important csrf Token -->
{% csrf_token %}
{{ form.media }}
{{ form|crispy }}
<input type="submit" class="btn btn-primary btn-lg" value="Approve">
</form>
</div>
...
<div id="demo" class="collapse">
<form method="POST" enctype="multipart/form-data">
<!-- Very Important csrf Token -->
{% csrf_token %}
{{ form_2.media }}
{{ form_2|crispy }}
<input type="submit" class="btn btn-primary btn-lg" value="Send">
</form>
</div>
Upvotes: 0
Views: 1071
Reputation: 169416
It'd be better to handle the forms in different view functions.
If you're bent on handling both forms in the same function, you will need to add a "marker" field that you check before you attempt to validate the form.
if request.method == 'POST' and request.POST.get('form') == 'risk':
form = PdfRiskForm(...)
elif request.method == 'POST' and request.POST.get('form') == 'comment':
form = ...
and then submit the form
field along with the form you're submitting:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="form" value="risk" /> <!-- or comment -->
Upvotes: 1
Reputation: 16515
Another approach could be to send each form to a different URL (each with its own view).
The 2 forms can still be in the same HTML page (same template), but you specify a different action
attribute for each.
<form method="POST" enctype="multipart/form-data"
action="/my-url-1/">
...
</form>
...
<form method="POST" enctype="multipart/form-data"
action="/my-url-2/">
...
</form>
This way you can simplify each view and no unnecessary data (meaning: the other forms data) gets POSTed to the views.
Upvotes: 0