Суммировать значения формы и добавить результат в базу данных
Я хочу сделать форму, которая имеет 3 числовых радио-значения, предположительно выглядящие следующим образом:
И я бы хотел, чтобы эти 3 значения суммировались и выводилась сумма этих значений, чтобы затем сохранить их в базе данных.
forms.py:
class FormTest(forms.Form):
CHOICES = [
('0', '0'),
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
]
num1 = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
num2 = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
num3 = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
total = num1 + num2 + num3
models.py:
class Test(models.Model):
num1 = models.IntegerField()
num2 = models.IntegerField()
num3 = models.IntegerField()
class Dato(models.Model):
dato = models.IntegerField()
views.py:
def formtest(request):
"""
if request.method == 'GET':
return render(request, 'testform.html', {
'form': FormTest()
})
else:
Test.objects.create(
num1=request.POST["num1"],
num2=request.POST["num2"],
num3=request.POST["num3"]
)
return redirect('forms')
"""
if request.method == 'GET':
return render(request, 'testform.html', {
'form': FormTest(),
})
else:
Dato.objects.create(
dato=request.POST['dato']
)
return redirect('forms')
testform.html:
{% extends 'layouts/base.html' %}
{% block content %}
<h1>Test Form</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button>Save</button>
</form>
{{ totalsum }}
{% endblock %}
urls.py:
from django.urls import path
from . import views
urlpatterns = [
#path('', views.index),
path('', views.index, name="index"),
path('about/', views.about, name="about"),
path('hello/<str:username>', views.hello, name ="hello"),
path('projects/', views.projects, name="projects"),
path('tasks/', views.tasks, name="tasks"),
path('create_task/', views.create_tasks, name="create_task"),
path('create_projects/', views.create_project, name="create_projects"),
path('formtest', views.formtest, name="forms")
]
Я знаю, что мне не разрешено суммировать ChoiceFields самостоятельно, но я понятия не имею, что на самом деле нужно сделать, чтобы это работало, я думаю, что я мог бы попробовать Javascript, но я не знаю, как его правильно встроить... Помогите? Пожалуйста?
Я просто не смог воспроизвести визуальный образ таким же образом, используя custom стилизацию в шаблоне, хотя это довольно близко.
Для того чтобы это работало, вам нужно получить данные из request.POST (в данном случае через форму django). Для сохранения объекта вы можете просто создать экземпляр объекта, используя форму clean_data kwargs:
Test.objects.create(**form.cleaned_data)
что эквивалентно:
Test.objects.create(
num1=form.cleaned_data.get('num1'),
num2=form.cleaned_data.get('num2'),
num3=form.cleaned_data.get('num3')
)
Но чтобы выполнить операцию с данными, сначала необходимо получить их из объекта clean_data формы. Эти данные приходят в строковом формате, поэтому их необходимо разобрать/преобразовать в целое число, чтобы выполнить нужную операцию:
number1 = int(form.cleaned_data.get('num1'))
number2 = int(form.cleaned_data.get('num2'))
number3 = int(form.cleaned_data.get('num3'))
total = number1 + number2 + number3
Одно из возможных решений:
models.py
from django.db import models
class Test(models.Model):
num1 = models.IntegerField()
num2 = models.IntegerField()
num3 = models.IntegerField()
# Not really necessary, just to show on template
def __str__(self):
total = self.num1 + self.num2 + self.num3
return f'{self.num1} + {self.num2} + {self.num3} = {total}'
forms.py (Как вариант, вы можете изучить model form для более чистого решения)
from django import forms
CHOICES = [
('0', '0'),
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
]
class SimpleForm(forms.Form):
num1 = forms.ChoiceField(
required=True,
widget=forms.RadioSelect({'class': 'myfieldclass'}),
choices=CHOICES,
initial=0
)
num2 = forms.ChoiceField(
required=True,
widget=forms.RadioSelect({'class': 'myfieldclass'}),
choices=CHOICES,
initial=0
)
num3 = forms.ChoiceField(
required=True,
widget=forms.RadioSelect({'class': 'myfieldclass'}),
choices=CHOICES,
initial=0
)
views.py
from django.shortcuts import render
from .forms import SimpleForm
from .models import Test
def select_number(request):
total = None
tests = Test.objects.all()
if request.method == 'POST':
form = SimpleForm(request.POST)
if form.is_valid():
# Save obj
Test.objects.create(**form.cleaned_data)
# cast data to interger, to show current test result
number1 = int(form.cleaned_data.get('num1'))
number2 = int(form.cleaned_data.get('num2'))
number3 = int(form.cleaned_data.get('num3'))
total = number1 + number2 + number3
else:
form = SimpleForm()
context = {'form': form, 'total': total, 'tests': tests}
return render(request, 'select_number.html', context)
select_number.html
{% extends 'base.html' %}
{% block content %}
<style>
.myfieldclass {
display: flex;
flex-flow: row nowrap;
}
</style>
<form action="{% url 'core:select-number'%}" method="post">
{% csrf_token %}
<table>
{{form}}
</table>
<button type="submit">Sum Up</button>
</form>
<br>
{% if total %}
The total of the current sum is {{total}}
{% endif %}
<hr>
<h2>My tests list</h2>
{% for test in tests %}
{{test}}<br>
{% endfor %}
{% endblock content %}
urls.py
from django.urls import path
from core import views
app_name = 'core'
urlpatterns = [
path('select/number/', views.select_number, name='select-number'),
]
Конечно, все это можно сделать с помощью Javascript, используя AJAX. Обычно это используется, когда вы не хотите, чтобы ваша страница полностью перезагружалась при отправке запроса к представлению.