I'm hoping someone can help me, i am a complete beginner with Flask and Postgres.
Basically, I created a python file, that takes user input to query the existing postgres database, this works perfectly. However, now I want to create a flask web app to do the exact same.
Accept the user will input the name on the html text box, and once the user hits submit, it needs to query the Postgresql database and return the requested columns for that specific row, exactly like the db_test.py file does.
Below is my python file that works and give me the expected results, but when I tried to create the app.py file with the html file, I am not able to get it to work, and I'm sure I'm missing something simple, but I don't know what.
This is the db_connect.py file that works - now I want to create the same results using flask and html.
# This is the db_test.py file which works as expected.
import psycopg2
# This section will try to create a Database Connection
try:
db_connection = psycopg2.connect(
host="localhost",
database="my_db",
user="postgres",
password="password",
port=5432
)
# This section will test Database Connection and return an exception if the connection fails.
print("Connected to server successfully")
except psycopg2.DatabaseError as Error:
print(f"Connection failed to server {Error}")
# This is the user input for that will be used to query the database table.
name = input("What is the name? ").title()
# This is the cursor for querying the Database table for the name that the user input and prints out the title, name and email
cursor.execute(
"SELECT id, name, email FROM details WHERE name = %s", (name,))
details = cursor.fetchall()
for d in details:
print(d)
# This Cursor closes the database connection and an If Statement to check and confirm that the database connection is closed.
cursor.close()
# This closes the connection to the Database
if db_connection:
db_connection.close()
print("Disconnected from server")
This is the second part of the project, with flask and html, but I can't get it to work.
This is the app.py file:
import creds
from flask import Flask, request, render_template
from flask_sqlalchemy import SQLAlchemy
# initialising the app
app = Flask(__name__)
app.config['SECRET_KEY'] = f"{creds.thisisasecret}"
# This is the Database URI
app.config['SQLALCHEMY_DATABASE_URI'] = f"postgresql://{creds.username}:{creds.password}#localhost:5432/{creds.database}"
app.config['SQLALCHEMY_TRACK_MODIFICATION'] = True
db = SQLAlchemy(app)
class Details(db.Model):
__tablename__ = 'details'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(length=50))
email = db.Column(db.String(length=30))
#app.route("/")
def show_details():
return render_template("index.html", details=details.query.all())
app.run(debug=True, host="127.0.0.1", port=3000)
And this is the index.html file which also displays the text box with a submit button, but when i enter the name, nothing happens.
<body>
<div>
DB Search
</div>
<div>
<form action="{{url_for('show_details')}}" method="GET">
<input type="text" name="title" placeholder="Name">
<button type="submit">Submit</button>
</form>
</div>
<hr/>
</body>
I have re-written the app.py and html file, I believe it's a lack of knowledge but all the research I'm doing online is not helping me fix this problem.
Basically when I type the name in the text box on the html page and click on submit, it should return the id, name and email on the html page.
Can someone please point me in the right direction?
Generally, to process form input with Flask, you'd define the form as below:
<form method="POST">
then, to process it in Flask:
#app.route("/", methods=["GET", "POST"])
def show_details():
if request.method == "POST":
form_data = request.form
name_entered_in_form = form_data["title"] # Access form field by `name=` parameter
new_details = ... # populate data based on name entered
return render_template("index.html", details=new_details)
return render_template("index.html", details=details.query.all())
this code provides details about all fields in the database by default, and when a name is passed in and submitted, it passes in just those details to the exact same page. Note how the same app route ("/") is able to handle both types of requests - GET requests for displaying data and POST requests for handling submitted data.
Related
Hi there I'm creating a Flask web app and now I have to create more cruds, so I decided to modularize the app using Blueprints.
I have a Login function on main.py that allows me to enter the app interface:
app.route('/', methods=['GET', 'POST'])
def login():
# Output message if something goes wrong...
msg = ''
# Check if "username" and "password" POST requests exist (user submitted form)
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
# Create variables for easy access
username = request.form['username']
password = request.form['password']
# Check if account exists using MySQL
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cursor.execute(
'SELECT * FROM accounts WHERE username = %s AND password = %s', (username, password,))
# Fetch one record and return result
account = cursor.fetchone()
# If account exists in accounts table in out database
if account:
# Create session data, we can access this data in other routes
session['loggedin'] = True
session['id'] = account['id']
session['username'] = account['username']
# Redirect to home page
return redirect(url_for('client.home'))
else:
# Account doesnt exist or username/password incorrect
msg = 'Incorrect username/password!'
# Show the login form with message (if any)
return render_template('index.html', msg=msg)
It redirects to this Blueprint:
from flask import Blueprint, render_template
from flask import render_template, request, redirect, url_for, session, flash
from flask_mysqldb import MySQL
import MySQLdb.cursors
import re
from extension import mysql
client = Blueprint('client', __name__,
static_folder="../static", template_folder="../templates")
#client.route('/')
def home():
if 'loggedin' in session:
cur = mysql.connection.cursor()
cur.execute('SELECT * FROM cliente')
data = cur.fetchall()
# User is loggedin show them the home page
return render_template('home.html', username=session['username'], cliente=data)
# User is not loggedin redirect to login page
return redirect(url_for('login'))
It works just fine, but with a condition. On my main.py I also have this:
#app.route('/home')
def home():
pass
And this is the problem, I don't know why I should keep this route on my main.py because if I delete it my app crashes and throws me this error:
werkzeug.routing.BuildError
werkzeug.routing.BuildError: Could not build url for endpoint 'home'. Did you mean 'client.home' instead?
I have no idea why does this happens.
Why should I keep this route? or What I'm doing wrong?
Could you please give me a hand?
I've trying to change the redirect to using multiple routes, but if I delete that /home route.. my app crashes anyway.
in url_for look for the name of the function ie url_for('function_name', parameters)
so to avoid the crash better to change the name of main.py home function to something else.
Solved: I had one ref to Home on other file: Layout.html.
Just removed the ref and it's solved
I am trying to set up a webhook on PythonAnywhere to connect to Twilio. I am essentially trying to create a very simple chatbot with if statements which choose a response based on the text message that comes in. I am now trying to add a databsae into the mix so that the response can also be based on previous texts as well. I have managed to set up the database but cant seem to get the text messages that are received to be stored in the database.
I have tried going on various tutorials and answer websites like this one but have not managed to get any of the potential solutions to work. They either break the code entirely so that no messages are sent in response or still nothing is stored in the database.
Code currently used
from flask import Flask, request, redirect, url_for
from twilio.twiml.messaging_response import MessagingResponse
from flask_sqlalchemy import SQLAlchemy
from socket import gethostname
app = Flask(__name__)
SQLALCHEMY_DATABASE_URI = "mysql+mysqlconnector://{username}:{password}#{hostname}/{databasename}".format(
username="UrbanMissions",
password="Hello123",
hostname="UrbanMissions.mysql.pythonanywhere-services.com",
databasename="UrbanMissions$ClueNumber",
)
app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI
app.config["SQLALCHEMY_POOL_RECYCLE"] = 299
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class Reply(db.Model):
__tablename__ = "messages"
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(4096))
[...]
if __name__ == '__main__':
db.create_all()
reply = Reply(content=request.values.get('Body', None)
db.session.add(reply)
db.session.commit()
if 'liveconsole' not in gethostname():
app.run()
#app.route('/', methods=['GET', 'POST', 'PUT'])
def main():
body = request.values.get('Body', None)
text = body.lower()
resp = MessagingResponse()
if text.find("start") == 0:
This is the code that seems to cause all the problems
("$reply = Reply(content=request.values.get('Body', None)
$db.session.add(reply)
$db.session.commit()")
it is my attempt to add the message that was sent in to the messages database but this doesn't seem to work. Any advice on how to get this to work to add the incoming message to the database would be really appreciated. Also what the code to retrieve the message again from the database would really help.
I am working on a flask app, which connects to a DB2 database and gets data from the database but only when users enter their DB2 database username and password through a form. I am using WTF element in database connection login form (app also has an app user login), below is what I am trying to do, I have placed all the database connections parameters inside a route
class DBForm(FlaskForm):
DBuser = StringField('DB.Username', validators=[DataRequired(), Length(1, 20)])
DBpass = PasswordField('DB.Password', validators=[DataRequired()])
remember_me = BooleanField('Remember me')
#app.route('/', methods=['GET', 'POST'])
def home():
form = DBForm()
if form.validate_on_submit():
USER_ID = form.DBuser.data
USER_PASS = form.DBpass.data
conn = ibm_db.connect("DATABASE=WDLAB; HOSTNAME=127.0.0.1; PORT=10000; PROTOCOL=TCPIP;UID=USER_ID;PWD=USER_PASS;", "", "")
cur = db2.conn.cursor()
cur.execute('select * from JOB_ROLE')
data = cur.fetchall()
return render_template('index.html',form=form,data=data)
return render_template('index.html', form=form)
conn.close()
HTML
<div class="container">
{{form.csrf_token }}
{{form.DBuser.label }}
{{form.DBuser }}
{{form.DBpass.label }}
{{form.DBpass }}
{{form.remember_me }}
<button type="submit">Connect</button>
</div>
this passes connection parameters to database, but fails to connect with an Incorrect User Name and Password Error, I was thinking if this error was because the username and password by this method is not passed within single quotes in conn, tried to concatenate quotes when I pass it to conn but that as well gives same outcome. request expert help please
You have to substitute the username and password in your DSN with the form data:
conn = ibm_db.connect("DATABASE=WDLAB; HOSTNAME=127.0.0.1; PORT=10000; PROTOCOL=TCPIP;UID={};PWD={};".format(USER_ID, USER_PASS), "", "")
I apologize for any misinformation from the title but I'm really not sure what the issue is. I'm creating a demo project that receives a user's name and age from an HTML form. Then, there are two buttons. One adds the information to an sqlite3 database called people.db. The other retrieves one person randomly from the database and displays it.
Here is my code:
import os
import sqlite3
from flask import Flask
from flask import request
from flask import render_template
from flask import g
app = Flask(__name__)
#app.route('/', methods=['POST', 'GET'])
def hello():
error = None
if request.form.get('submit', None) == "add":
if request.form['name'] and request.form['age']:
name = request.form['name']
age = request.form['age']
database = connect_db()
cursor = database.cursor()
sql = "INSERT INTO person (name, age) VALUES ({0}, {1});".format(name, age)
cursor.execute(sql)
database.commit()
return render_template("index.html")
else:
error = "Name or age not provided."
return render_template('index.html', error=error)
elif request.form.get('submit', None) == "retrieve":
database = connect_db()
cursor = database.cursor()
sql = "SELECT * FROM person ORDER BY RANDOM() LIMIT 1;"
cursor.execute(sql)
result = cursor.fetchone()
return render_template("index.html")
return render_template("index.html")
if __name__ == "__main__":
app.run(host=os.getenv('IP', '0.0.0.0'),port=int(os.getenv('PORT', 8080)))
So, the issue is that when I run the program on Cloud 9's c9users.io platform, it attempts to go to http://project-username.c9users.io:8080/localhost/?name=name&age=22&submit=add. I don't understand why it's trying to access localhost here. My program's structure is as follows:
\website-test
\templates
index.html
hello.py
people.db
So, I suppose it should be returning to the root of the website while performing the desired functionality. How do I achieve that?
Thank you!
Here, also, is my index.html:
<!DOCTYPE html>
<html>
<head>
<title>WEBSITES</title>
</head>
<body>
<h2>Please enter your name and age.</h2>
<form action="localhost/">
<input type="text" name="name" placeholder="name">
<input type="text" name="age" placeholder="age">
<input type="submit" name="submit" value="add">
<input type="submit" name="submit" value="retrieve">
</form>
</body>
</html>
By default Flask run your application on localhost. Add below lines of code to end of the file.
if __name__ == "__main__":
app.run(host='0.0.0.0')
0.0.0.0 here means, the app will take the host as your ip and will be accessible publically. For further reference read here in documentation.
What is in your index.html? Sounds like you have action="localhost/" on the form element
I've found a lot of into similar to this, but I just can't quite make it work. Basically, I've got a button, and upon pressing it, I want to fire that value back to my flask backend.
HTML Button:
<form action="" method="POST" ><button class="btn btn-danger" type="submit" name="delete" value="{{ item2 }}"><span class="glyphicon glyphicon-trash"></span> Delete</button> </form>
Python:
#app.route('/', methods=["GET","POST"])
def home():
if request.method == 'POST':
if request.form['delete'] == post_id:
(my sql login/cursor stuff....)
sql = "DELETE FROM test_table WHERE post_id = ?"
c.execute(sql, (post_id,))
return redirect("/")
As you can see, I'm populating the links (and subsequent variable) with jinja. It populated the button as it should, but sending it back to my python script isn't working.
UPDATE:
When I run this, I get an internal server error. I cannot see what the routing error is because I can't get debug to work (using wsgi/werkzeug).
I think we can conclusively say is that by not defining post id is why it's not working. So my question is, when the button sends data BACK to python, what value (and how) does python grab? is it name= or value= or something else?
Your problem is
request.form['delete'] == post_id
You get value from button (request.form['delete']) and try to compare with value in variable post_id which doesn't exists.
If you want to get value from button and assign to variable post_id then you need
post_id = request.form['delete']
or
post_id = request.form.get('delete')
and then you can use post_id in SQL query.
#app.route('/', methods=["GET","POST"])
def home():
if request.method == 'POST':
post_id = request.form.get('delete')
if post_id is not None:
(my sql login/cursor stuff....)
sql = "DELETE FROM test_table WHERE post_id = ?"
c.execute(sql, (post_id,))
return redirect("/")