Proven Paradox
Proven Paradox

Reputation: 67

In Django, how do I add the contents of two fields and display the results in a third field?

I'm trying to learn Django and am finding it frustratingly difficult to do fairly basic things. I have the following form classes:

from django import forms

class InputForm(forms.Form):
  field1 = forms.FloatField(label="First field: ")
  field2 = forms.FloatField(label="Second field: ")

class OutputForm(forms.Form):
  outfield = forms.FloatField(label="Result: ")

And the following template:

<form>
    {{ input_form.as_ul }}
    <input type="submit" class="btn" value="Submit" name="submit_button">
</form>

<form>
    {{ output_form.as_ul }}
</form>

And finally, the following view:

from django.shortcuts import render
from .forms import InputForm, OutputForm

def index(request):

    if request.GET.get('submit_button'):
        # ?????

    else:
        input_form = InputForm()
        output_form = OutputForm()
        return render(request, 'index.html', {'input_form': input_form, 
                                            'output_form': output_form})

All I want to happen is that when I hit the submit button, the values in first field and second field get added and displayed in the result field. I know from debug outputs that the ????? commented block is run when I press the button, but I have so far not been able to figure out what to do to actually access or alter the data in my fields. I don't care about keeping a record of these transactions so it feels like storing these in a database is tremendous overkill. What is the correct way to approach this?

Upvotes: 2

Views: 630

Answers (3)

Alasdair
Alasdair

Reputation: 308959

You don't need a form to display the result. When the form is valid, you can get the values from the form's cleaned_data and calculate result.

def index(request):
    result = None  # Set to None by default

    if request.GET.get('submit_button'):  # The submit button was pressed
        input_form = InputForm(request.GET)  # Bind the form to the GET data
        if input_form.is_valid():
            result = input_form.cleaned_data['field1'] + input_form.cleaned_data['field2']  # Calculate the result
    else:
        input_form = InputForm()  # Submit button was not pressed - create an unbound (blank) form
    return render(request, 'index.html', {'input_form': input_form, result:result})

Then in your template, include {{ result }} instead of the output form.

Upvotes: 0

kagronick
kagronick

Reputation: 2688

Setting the initial poperty on a field prefills it:

output_form.fields['outfield'].initial = input_form.data.get ('field1') + input_form.data.get ('field1')

You need to pass request.POST or request.GET into OutputForm when you instantiate it. You should also be calling is_valid() on the from and using cleaned_data instead of data after you check if it is valid.

Upvotes: 0

Tom Dalton
Tom Dalton

Reputation: 6190

There's a few things at work here, lets go through them one by one.

1. Calculating the output value

Use the request data to build the form, validate it, and then calculate the sum:

if request.GET.get('submit_button'):
    input_form = InputForm(request.GET)
    if input_form.is_valid():
       data = input_form.cleaned_data
       result = data["field1"] + data["field2"]

2. Read-only output

It's not clear why you're using a submittable form field for data that is to be calculated by your app, as opposed to playing the result into a regular html 'label' in the template. If you really want/need to set the result in a form field, I'd at least make it read-only. See In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited? for an example of how to do that.

3. Set the output data in the form

Set the output form/field's initial data to the result you have calculated. following on form the code at (1):

       result = data["field1"] + data["field2"]
       output_form = OutputForm(initial={"outfield": result})

then render the view as you're already doing:

       return render(
           request,
           'index.html',
           {'input_form': input_form, 'output_form': output_form},
       )

Upvotes: 1

Related Questions