Submit button of the form in flask is not working - python

Submit button of the form is not working. After submitting the form,it should redirect to the next page but nothing is happening. On submit, it was supposed to redirect to the link localhost:5000/dashboard-data and then print the data on the web page. Please if anybody could help me. I have provided as much details as I could.
This is dashboard.py
import os
import random
import pandas as pd
from flask import Flask, render_template , request
import sqlite3
import matplotlib.pyplot as plt
import matplotlib
PEOPLE_FOLDER = os.path.join('static')
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = PEOPLE_FOLDER
data = pd.read_excel('C:\\Users\\Desktop\\Projects\\api\\Tweet_qlik_first.xlsx')
from sqlalchemy import create_engine
engine = create_engine('sqlite://', echo=False)
#app.route('/', methods=['GET', 'POST'])
def homepage():
if request.method=='GET':
matplotlib.use('Agg')
data.to_sql('users', con=engine)
topic_list=engine.execute("SELECT distinct Topic FROM users").fetchall()
count=engine.execute('''Select Topic,count(*) from users group by Topic''',).fetchall()
print(count)
x = []
y = []
for tr in count:
x.append(tr[0])
y.append(tr[1])
plt.bar(x,y)
plt.gcf().subplots_adjust(bottom=0.15)
plt.xlabel('Topics')
plt.ylabel('Tweet Count')
ax = plt.gca()
plt.setp(ax.get_xticklabels(), rotation=30, horizontalalignment='right')
plt.tight_layout()
x=random.randint(0,9999999)
img_name='plot'+str(x)+'.png'
plt.savefig('static/'+img_name)
full_filename = os.path.join(app.config['UPLOAD_FOLDER'], img_name)
tl=[]
for tr in topic_list:
tl.append(tr[0])
return render_template("main.html",topics=tl,img=full_filename)
#app.route('/dashboard-data',methods=['GET','POST'])
def result():
if request.method=='POST':
result=request.form["topic_list"]
topic_fcount=engine.execute('''Select Topic,"Follower Count" from users where Topic=?''',(str(result),)).fetchall()
return render_template("dashboard.html")
if __name__ == "__main__":
app.run(debug=True)
This is main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action = "/dashboard-data" method = 'POST'>
Topic
<select name="topic_list">
{% for each in topics %}
<option value="{{each}}" selected="{{each}}">{{each}}</option>
{% endfor %}
</select>
<input type="button" value="Submit"/>
</form>
</body>
<img src="{{ img }}" alt="User Image" >
</html>
This is dashboard.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for row in topic_fcount %}
{{row}}
{%endfor%}
</body>
</html>

Submit button of the form is not working. After submitting the form,it should redirect to the next page but nothing is happening.
Try changing the button to:
<input type="submit" value="Submit" />

You defined your button as a button, not as a submit.
You just need to edit your button from
<input type="button" value="Submit"/>
to
<input type="submit" value="Submit"/>
and you will have success.

Related

For Loop on RadioField not working Flask Python

Here is my main.py file
from flask import Flask, render_template, redirect, url_for, request
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, SelectField, RadioField
from wtforms.validators import DataRequired, URL
questions = ["1+1=2", "2+2=4", "3+3=7"]
correct = [1, 1, 0]
app = Flask(__name__)
app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b'
Bootstrap(app)
class Answers(FlaskForm):
choices = RadioField('Label', coerce=int, choices=[(1, 'True'), (0, 'False')], validators=
[DataRequired()])
class Submit(FlaskForm):
done = SubmitField('Submit')
#app.route('/', methods=['GET', 'POST'])
def answer():
form = Answers()
submit = Submit()
print(form.validate_on_submit())
if request.method == "POST":
print(request.form['choices'])
return redirect(url_for('score'))
return render_template('index.html', questions=questions, correct=correct, form=form, submit=submit)
#app.route('/results')
def score():
return render_template("result.html")
if __name__ == "__main__":
app.run(debug=True)
And here is my index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Exam Web-Application</title>
{% import "bootstrap/wtf.html" as wtf %}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<link href="static/css/styles.css" rel="stylesheet">
</head>
<body>
<div class="questions">
{% for x in range(0,3) %}
<div>
<div class="panel panel-default">
<div class="panel-heading">Question {{ x + 1}}:</div>
<div class="panel-body">
<div>
<p> {{ questions[x] }} </p>
{{ wtf.quick_form(form) }}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{{ wtf.quick_form(submit, button_map={"done": "primary"}) }}
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
</body>
</html>
So in the POST method, I want to get and print all the selected values of all RadioField choices but the current code prints an empty list it returns nothing, what am I doing wrong, can we not use loops to make multiple Fields and get the inputted value as a list?

jinja2.exceptions.UndefinedError: 'btn' is undefined

I am getting jinja2.exceptions.UndefinedError: 'btn' is undefined exception while logging to the localhost. The btn is properly defined but still.. Can I plaese get the help as soon as possible. Thank You in Advance
Python code- This code is the Python Code
from flask import Flask, render_template, request, send_file
from flask_sqlalchemy import SQLAlchemy
from send_email import send_email
from sqlalchemy.sql import func
from werkzeug import secure_filename
app=Flask(__name__)
#app.route("/")
def index():
return render_template("index.html")
#app.route("/success", methods=['POST'])
def success():
global file
if request.method=='POST':
file=request.files["file"]
file.save(secure_filename("uploaded" + file.filename))
with open("uploaded"+file.filename,"a") as f :
f.write("This was added later!")
return render_template("index.html", btn="download.html")
#app.route("/download")
def download():
return send_file("uploaded" + file.filename, attatchment_filename="yourfile.csv", as_attatchment=True)
if __name__ == '__main__':
app.debug=True
app.run()
HTML-
Index file - This is the main file
<!DOCTYPE html>
<html lang="en">
<title> Data Collector App</title>
<head>
<link href="../static/main.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Collecting Height</h1>
<h3>Please Fill the Entries to get Population Statistics on Height</h3>
<div class="message">
{{text | safe}}
</div>
<form action="{{url_for('success')}}" method="POST" enctype="multipart/form-data">
<input type="file" name="file" > <br>
<button type="submit">Submit</button>
</form>
{%include btn ignore missing%}
</div>
</body>
</html>
Download file- This is the html file for downloading. After importing the file this html code will create a button in the same index.html page so that I can also downoad the same file
<!DOCTYPE html>
<html lang="en">
<div class="download">
<button class="btn"> Download </button>
</div>
</html>
Was facing the same issue. My workaround was to replace:
{% include btn ignore missing %}
with
{% if btn %}
{% include btn %}
{% endif %}
This should work:
{% include [btn] ignore missing %}
The reason for change is due to a Flask update from the time when that video was created

jinja2.exceptions.TemplateNotFound why does this keep popping up?

This is my code pro.py which i have save in my Downloads:
from flask import Flask, render_template, flash, session, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField
app = Flask(__name__)
app.config['SECRET_KEY'] = 'kmkey'
class SimpleForm(FlaskForm):
breed = StringField('What breed are you?')
submit= SubmitField('Click Me')
#app.route('/',methods=['GET','POST'])
def imp():
form = SimpleForm()
if form.validate_on_submit():
session['breed'] = form.breed.data
flash(f"You just changed your breed to: {session['breed']}")
return redirect(url_for('imp'))
return render_template('imp.html',form=form)
if __name__ == '__main__':
app.run(debug=True)
This is my html code imp.html which i have saved in my template folder which is inside Downloads:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% for mess in get_flashed_messages() %}
<div class="alert alert-warning alert-dismissible fade show" role='alert'>
<button type="button" class="fade close" data-dismiss='alert' aria-label='close' >
<span aria-hidden='true'>×</span>
</button>
{{mess}}
</div>
{% endfor %}
<form method="post">
{{form.hidden_tag()}}
{{form.breed.label}}{{form.breed}}
{{form.submit()}}
</form>
</body>
</html>
Now when i run my python file on web it throws an error saying that
jinja2.exceptions.TemplateNotFound:imp.html why does it happen like that??
Can anyone pls help me out with this issue.
You need to save it in templates folder not template folder.

making a todo list using pickle and flask

i'm trying to make a simple todo list using flask and a text file database, for now I'm trying to add items and save it in a text file, and also show the items online, but I'm not sure what I'm going wrong,this is the code i have for now
from flask import Flask, render_template, request, redirect, url_for
import todo_list
app = Flask(__name__)
#app.route('/')
def index():
with open('programming.pkl', 'rb') as output:
new_list = todo_list.pickle.load(output)
return render_template('index.html', todo1=new_list, todo=todo )
#app.route('/task', methods=['GET''POST'])
def task():
if request.method == 'POST':
todo = request.form.get('todo')
with open('programming.pkl', 'wb+') as output:
todo_list.pickle.dump(todo, output)
return redirect('/')
and this is my HTML code, i have just used google.com as a place holder for now
<!DOCTYPE html>
<html>
<head>
<h1> TODO APP</h1>
</head>
<body>
<p>
<br>
<h2>Here are your todo items</h2>
</p>
<br>
<h3>{{ todo }}</h3>
<h4>Mark as done</h4>
<br>
<h3>{{ todo }}</h3>
<h4>Mark as done</h4>
<br>
<h3>stuff1</h3>
<h4>Mark as done</h4>
<br>
<form action="/task" method="POST">
<h3>Create todo</h3>
<input type="text" id="todo" name="todo"><br><br>
</form>
</body>
</html>

Flask-Sqlite posting to DB from webform

I have started just learning Flask and tried to find an answer how to post to SQLite DB from webform. So far haven't managed to get it work and bit lost with this. I manage to print values from DB based on code sample from simplypython but don't know how to add new ones from webform.
I would need to be able to address elements, open connection to the database, Insert values, save and close the connection. As far as I am aware I should add the POST method to the app.py and use request.form statement to pull the elements when submit button is pressed.
then the code should automatically display all the values on index html, which already works. could you please help me with the code I need to add to app.py file to get values added to DB and what to add to form action webform-section on html file?
index.html
<!DOCTYPE html>
<html>
<head>
<title>Flask Intro</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
</head>
<body>
<div class="container">
<h3 potsit </h3>
{% for post in posts %}
Titleotsikko: {{post.title }} <br>
Postotsikko: {{post.description}}
{% endfor %}
</div>
<div>
<form action="/????????????NOT SURE WHERE TO DIRECT" method="post">
<div>
<label for="title">title:</label>
<input type="text" id="title" />
</div>
<div>
<label for="description">description:</label>
<input type="text" id="description" />
</div>
<div class="button">
<button type="submit">Add to db</button>
</div>
</form>
</div>
</body>
</html>
app.py
from flask import Flask, render_template, request, session, g
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
if __name__=='__main__':
app.run(debug=True)
sql.py
import sqlite3
with sqlite3.connect("sample.db") as connection:
c = connection.cursor()
c.execute("DROP TABLE posts")
c.execute("CREATE TABLE posts(title TEXT, description TEXT)")
c.execute('INSERT INTO posts VALUES("Luck", "no luck.")')
EDIT
I made some changes based on the suggestion from Paul Rooney and created file called post.html, moved the form there from index.htmland added another #route on the app.py file. I believe I'm not far off but after trying to figure this out since Tuesday hoping to get it work. Unfortunately now I receive an error 405 'The method is not allowed for the requested URL.' and I'm stuck with this after trying different options.
post.html
<!DOCTYPE html>
<html>
<head>
<title>Flask post</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
</head>
<body
<div>
<form action="/post" method="post">
<div>
<label for="title">title:</label>
<input type="text" id="title" />
</div>
<div>
<label for="description">description:</label>
<input type="text" id="description" />
</div>
<div class="button">
<button type="submit">Add to db</button>
</div>
</form>
</div>
</body>
</html>
(edited) app.py
from flask import Flask, render_template, request, session, g, redirect, url_for
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
#app.route('/post', methods=['POST'])
def post():
title=request.form['title']
description=request.form['description']
print title, description
return redirect(url_for('/'))
if __name__=='__main__':
app.run(debug=True)
To answer your original question you should pick an endpoint to post your data to and use that in both your flask app and the html form action.
I suggested post in comments but it could be anything. I think you've grasped what to do here but for completeness.
The HTML
<form action="/post" method="post">
The Python Code
Add a route to handle the POSTed data.
#app.route('/post', methods=['POST'])
def post():
# Do db stuff then redirect back to index page.
pass
Edited Question
You have an indentation error in your code, which is causing the 405 error. Your post function is inside your home function. Make it more like this
app.py
from flask import Flask, render_template, request, session, g, redirect, url_for
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
# One level of indentation removed from here downwards
#app.route('/post', methods=['POST'])
def post():
title=request.form['title']
description=request.form['description']
return redirect(url_for('home'))
if __name__=='__main__':
app.run(debug=True)
After that I see a 400 Bad Request error, which stems from the fact that you don't have name parameters in your html form.
The attempt to access the title and description values in the form dict in app.py will throw a KeyError exception, as those keys will not be present without the name parameter in the html.
If you add them e.g.
...
<input type="text" id="title" name='title'/>
...
<input type="text" id="description" name='description'/>
...
Then it will run all the way through your function.
The next issue will be
redirect(url_for('/'))
instead use
redirect(url_for('home'))
home being the name of the function called for path '/'.
After that you should be good to go.

Categories