2

I am working on an assignment for a Flask application with a function that does different things based on the value of a hidden field in a form on the index.html page. I am to have only two routes: '/' (index.html) and '/process' (which performs actions on index.html).

When I run this in Flask (python server.py in a virtualenv), and click the button "Make Money" on index.html, I get this error:

"TypeError TypeError: 'ImmutableMultiDict' object is not callable"

Can someone please tell me how I can get the desired value from the hidden input?

contents of server.py

import datetime
import random
from flask import Flask, render_template, redirect, request, session

app = Flask(__name__)
app.secret_key = 'fooBarBaz'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/process', methods=['GET','POST'])
def process():
    if request.method == 'POST':
        target = request.form('name')
        if target == 'clothing':
            new_money = random.randrange(10, 21)
            session['balance'] += new_money
            timestamp = datetime.datetime.now()
            session['register'] += ("Received" + new_money + " dollars at " + timestamp.strftime("%Y/%m/%d %I:%M %p")) 
        return render_template('index.html')

app.run(debug=True)

contents of index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div container>
        <div class='balance'>
            <p>Your balance:  {{ session['balance'] }}</p>
        </div>
        <div class="shops">
            <div class="clothing">
                <h2>Clothing Store</h2>
                <p>(earns 10 - 20 dollars)</p>
                <form action="/process" method="post">
                    <input type="hidden" name="clothing">
                    <input type="submit" value="Make Money!">
                </form>
            </div> 
        </div> 
        <div class="register">
            <h4>Receipt Tape</h4>
            <p>{{ session['register'] }}</p>
        </div>
    </div>
</body>
</html>
Karen Clark
  • 166
  • 2
  • 4
  • 12
  • 1
    `target = request.form('name')` cannot work, just use brackets instead. but you don't have any input named `"name"`, should it be `clothing` maybe ? – PRMoureu Jun 16 '18 at 20:55
  • 1
    btw, you may facing another issue with `session['balance'] += new_money`, if `session['balance']` is not declared before, you cannot use this operator – PRMoureu Jun 16 '18 at 20:58

1 Answers1

4

The form should be something like below, with a value defined for the hidden input:

<form action="/process" method="post">
    <input type="hidden" name="clothing" value="clothing">
    <input type="submit" value="Make Money!">
</form>

Without changing the logic too much, the register section could accept html tags to render linebreaks

<p>{{ session['register']|safe }}</p>

Then with minimal changes, this is how you could resolve some issues you are facing in the view. To avoid error about session key not declared, the best way is to used the method get with 0, or "" instead of the None returned when the key is not found:

@app.route('/process', methods=['GET','POST'])
def process():

    if request.method == 'POST':
        target = request.form.get('clothing')
        if target == 'clothing':
            new_money = random.randrange(10, 21)
            session['balance'] = session.get('balance',0) + new_money
            timestamp = datetime.datetime.now()
            session['register'] = "{}<br>Received {} dollars at {}".format(
                session.get('register',''),
                new_money,
                timestamp.strftime("%Y/%m/%d %I:%M %p"))
        return render_template('index.html')
PRMoureu
  • 12,817
  • 6
  • 38
  • 48