-1

I'm new to flask and web programming in general. I'm trying a simple example. I have a HTML base template that shows a text box and a picture of an animal. The template is rendered by flask. The idea is that a user can type the name of a new animal in the text box and the picture changes to the new animal.

I tested the code. There is a problem - that the input text given in the html textbox doesn't seem to go to the proper app.route. Or at least I can't figure out (as I'm running on pythonanywhere and the print statements in the server don't show up on console).

Here is the code and the template. Please let me know what I'm doing wrong. Thanks!

Here is the flask_app.py:

  from flask import render_template
  from flask import request, redirect
  from flask import Flask
  app = Flask(__name__)

  @app.route('/')
  def index():
    imgname = "tiger2.png"
    return render_template('untitled1.html', title='TIGER', fname=imgname)

  @app.route('/', methods=['POST', 'GET'])
  def imgshow(animal):
   #assert request.method == 'POST'
   #print("New request!")

   animal = request.form['animal']
   if animal.lower() == 'tiger':
      imgname = 'tiger2.png'
   elif animal.lower() == 'lion':
      imgname = 'lion1.png'
   elif animal.lower() == 'panther':
      imgname = 'panther.png'
   else:
      imgname = 'lion1.png'

   return render_template('untitled1.html', title=animal.upper(), fname=imgname)

And here is the template untitled1.html

<!DOCTYPE html>
<html>
<head>
 <title>{{ title }}</title>
</head>
<body>
<!-- Serving an Image -->

 <h1>Hello, World!</h1>

 <form action="">
  <label for="animal">Animal: </label>
  <input type="text" id="animal" name="animal"><br><br>
</form>


 <img src="{{ url_for('static', filename=fname ) }}" alt="Tiger">
</body>
</html>
Brad
  • 1

3 Answers3

0

Try this:

from flask import render_template
from flask import request, redirect
from flask import Flask
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
  def index():
    if request.method == 'GET':
        imgname = "tiger2.png"
        title='TIGER'
    else:
        variants = {
            'tiger': 'tiger2.png',
            'lion': 'lion1.png',
            'panther': 'panther.png'
        }
       animal = request.form.get('animal').lower()
       imgname = variants.get(animal)
       title = animal.upper()
    return render_template('untitled1.html', title='TIGER', fname=imgname)
shoytov
  • 585
  • 4
  • 10
  • `animal = request.form.get('animal').lower()` may raise error if the animal entered is not in list. `request.form.get('animal')` may return None that does not have `lower()` method. – Kate Melnykova Apr 06 '20 at 18:26
  • Thanks! This certainly is interesting. But typing the animal name in the text box ("lion" for instance) is not changing the image. It is still the default tiger. And the typing it in the text box adds this at the end of the URL: ?animal=lion (my testing website is bpudiped.pythonanywhere.com, but I will try the other suggestion in the meantime so it might be shaky). Thanks again! – Brad Apr 06 '20 at 18:53
0

app.route registers that under the given web address (in your case \), the function listed just below be implemented. The problem is that you have two functions registered under the same route which means that the first registration is erased.

You don't need the first app.route. It basically should say that the default value of an animal is a tiger. The second function should be modified as below:

display_map = {
    'tiger': 'tiger2.png',
    'lion': 'lion1.png',
    'panther': 'panther.png'
    }

@app.route('/', methods=['POST', 'GET'])
  def imgshow(animal):
   if request.method == 'POST':
       animal = request.form.get('animal', 'lion').lower()
       imgname = display_map.get(animal, 'lion1.png')
       return render_template('untitled1.html', title=animal.upper(), fname=imgname)

   else:
       return render_template('untitled1.html', title='TIGER', fname='tiger.png')       

And you also need to actually submit results to the server.

<html>
<head>
 <title>{{ title }}</title>
</head>
<body>
<!-- Serving an Image -->

 <h1>Hello, World!</h1>

 <form method="POST">
  <label for="animal">Animal: </label>
  <input type="text" id="animal" name="animal"><br><be>
  <input type="submit" name="submit" value="submit">
</form>


 <img src="{{ url_for('static', filename=fname ) }}" alt="Tiger">
</body>
</html>
Kate Melnykova
  • 1,863
  • 1
  • 5
  • 17
  • Thanks, I tried this (after changing display_map.get line to display_map[animal]. IT didn't run (500 internal server error) and I can't get any debug statements out. however, I think I understand the code and will try it again later. But will it really work in this case: load webpage (showing default Tiger image), enter "lion" in text box => image should change to lion. It is not happening for the code from the other comment (to which I responded). Thanks. – Brad Apr 06 '20 at 19:06
  • I also added updated html file. One of the problems that the form was transmitted via get request instead of the post request. Also, at what stage does the error occur (initial loading, submitting the name of the animal, etc.)? – Kate Melnykova Apr 07 '20 at 02:30
0

For me, the best approach is to use only the GET method:

from flask import Flask, render_template, request, redirect

app = Flask(__name__)

animals = {'tiger': 'tiger2.png', \
        'lion': 'lion1.png', \
        'panther': 'panther.png'}


@app.route('/')
def index():
    animal = request.args.get('animal', 'tiger')
    image = animals.get(animal, 'lion')
    return render_template('untitled1.html', title=animal.upper(), fname=image)

The POST method is best when you need to do some processing (write data from the database) and then redirect to another GET route.

Claudio Acioli
  • 319
  • 1
  • 7