Reputation: 19
I want to make a form that has 3 number radio values, supposedly look like this:
And I'd like for those 3 values to sum and display the sum of those values to then save them into the database.
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")
]
I know I'm not allowed to sum ChoiceFields on its own but I have no idea what to actually do to make it work, I guess I could try a Javascript but I don't know how to incorporate it, correctlly... Help? Please?
Upvotes: 0
Views: 36
Reputation: 3798
I just could not reproduce the visual in the same way, by using a custom styling in the template, although it is pretty close.
To make it work you need to retrieve the data from the request.POST (in this case via django form). To save the object you can just create an object instance using the form cleaned_data kwargs:
Test.objects.create(**form.cleaned_data)
which is equivalent to:
Test.objects.create(
num1=form.cleaned_data.get('num1'),
num2=form.cleaned_data.get('num2'),
num3=form.cleaned_data.get('num3')
)
But, to do an operation with the data, first, you need to retrieve it from the form's cleaned_data object. This data comes in string format, so it is necessary to parse / convert into an integer in order to do the wanted operation:
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
One possible solution:
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 (Optionally, you can explore model form for a cleaner solution)
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'),
]
Of course, it is possible to do all of that with Javascript using AJAX. Usually used when you do not want to your page to be entirely reloaded when sending a request to a view.
Upvotes: 1