Сохранение и отображение входов формы Django при отправке POST
--ПРОБЛЕМА--
Я создал базовый калькулятор, используя Django. Приложение принимает некоторые основные вводы формы перед выполнением некоторых вычислений и возвращает результаты пользователю, однако я хочу, чтобы вводы пользователя оставались видимыми в форме при отправке. В настоящее время происходит следующее.
- Пользователь вводит значения в форму и отправляет с помощью кнопки "Рассчитать".
- Результаты возвращаются, как ожидалось, но форма и значения больше не присутствуют.
- Пользователь может нажать кнопку "Рассчитать", чтобы вернуться к началу процесса и пустой форме.
- ЖЕЛАЕМЫЙ РЕЗУЛЬТАТ-
--КОД--
forms.py
from django import forms
class InvestmentForm(forms.Form):
starting_amount = forms.FloatField()
number_of_years = forms.FloatField()
return_rate = forms.FloatField()
annual_additional_contribution = forms.FloatField()
views.py
from django.shortcuts import render
from django.views import View
from .forms import InvestmentForm
class Index(View):
def get(self, request):
form = InvestmentForm()
return render(request, 'loancalculator/index.html', {'form': form})
def post(self, request):
form = InvestmentForm(request.POST)
if form.is_valid():
total_result = form.cleaned_data['starting_amount']
total_interest = 0
yearly_results = {}
for i in range(1, int(form.cleaned_data['number_of_years'] +1)):
yearly_results[i] = {}
# CALCULATE THE INTEREST
interest = total_result * (form.cleaned_data['return_rate'] / 100)
total_result += interest
total_interest += interest
# ADDITIONAL CONTRIBUTION
total_result += form.cleaned_data['annual_additional_contribution']
# SET YEARLY RESULTS
yearly_results[i]['interest'] = round(total_interest, 2)
yearly_results[i]['total'] = round(total_result,2)
# CREATE CONTEXT
context = {
'total_result': round(total_result,2),
'yearly_results': yearly_results,
'number_of_years': int(form.cleaned_data['number_of_years'])
}
# RENDER THE TEMPLATE
return render(request, 'loancalculator/index.html', context)
else:
form = InvestmentForm()
return render(request, 'loancalculator/index.html', {'form':form})
index.html
{% extends 'loancalculator/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row justify-content-center">
<div class="col-4 border bg-light">
<div class="row t-5">
<div class="col-12 col-md-6 mx-md-auto">
<h1> Investment Calculator</h1>
<h5> Enter the details below to see your estimate</h5>
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">Calculate</button>
</form>
<br>
</div>
</div>
</div>
<div class="col-4 border">
<div class="row t-5">
<div class="col-12 col-md-6 mx-md-auto">
<h1>Investment Results</h1>
<h3> After {{ number_of_years }} years, your investment is worth ${{ total_result }}</h3>
<div class="mt-5">
<table class="table">
<thead>
<tr>
<th scope="col">Year</th>
<th scope="col">Interest</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
{% for key, value in yearly_results.items %}
<tr>
<th scope="row">{{ key }}</th>
<td>{{ value.interest }}</td>
<td>{{ value.total }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
При создании контекста значение 'form' не устанавливается (views.py, в разделе get())
Два способа, которыми вы можете добиться желаемого, как я это вижу:
Метод 1
.
Используйте sessions для хранения данных, а затем перенаправьте их в форму, используя initial значения формы. Это, вероятно, самый простой вариант, поскольку он наиболее точно соответствует тому, что у вас уже есть.
from django.shortcuts import render
from django.views import View
from .forms import InvestmentForm
class Index(View):
def get(self, request):
# Fill in the initial values on the unbound form:
initial = {
'starting_amount': request.session.get('starting_amount'),
'number_of_years': request.session.get('number_of_years'),
'return_rate': request.session.get('return_rate'),
'annual_additional_contribution': request.session.get('annual_additional_contribution'),
}
form = InvestmentForm(initial=intial)
return render(request, 'loancalculator/index.html', {'form': form})
def post(self, request):
form = InvestmentForm(request.POST)
if form.is_valid():
# After getting the cleaned_data, set a session variable to hold it
total_result = form.cleaned_data['starting_amount']
request.session['starting_amount'] = total_result
number_of_years = int(form.cleaned_data['number_of_years']
request.session['number_of_years'] = number_of_years
return_rate = form.cleaned_data['return_rate']
request.session['return_rate'] = return_rate
annual_additional_contribution = form.cleaned_data['annual_additional_contribution']
request.session['annual_additional_contribution'] = annual_additional_contribution
total_interest = 0
yearly_results = {}
for i in range(1, number_of_years +1)):
yearly_results[i] = {}
# CALCULATE THE INTEREST
interest = total_result * (return_rate / 100)
total_result += interest
total_interest += interest
# ADDITIONAL CONTRIBUTION
total_result += annual_additional_contribution
# SET YEARLY RESULTS
yearly_results[i]['interest'] = round(total_interest, 2)
yearly_results[i]['total'] = round(total_result,2)
# CREATE CONTEXT
context = {
'total_result': round(total_result,2),
'yearly_results': yearly_results,
'number_of_years': number_of_years)
}
# RENDER THE TEMPLATE
return render(request, 'loancalculator/index.html', context)
else:
form = InvestmentForm()
return render(request, 'loancalculator/index.html', {'form':form})
Метод 2
.
Из того, что вы показываете здесь, в любом случае, вы могли бы просто использовать JavaScript для выполнения вычислений, захватывая значения непосредственно из DOM после их ввода, выполняя вычисления на передней стороне с помощью JavaScript, а затем заполняя значения, указывая места, где вы хотите, чтобы результаты отображались в DOM. Нет необходимости в формах, нет перезагрузки страниц.