When I specify an IP and port without the preceding:
if __name__ == '__main__':
As such:
app.run(host="138.165.91.210",port=5017,threaded=True)
It works but it hangs a bit (does it hang on an infinite loop maybe?). When I do the usual:
if __name__ == '__main__':
app.run(host="138.165.91.210",port=5017,threaded=True)
It avoids the ip and port. What's wrong with my code?
Full script:
import os
from sqlite3 import dbapi2 as sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash
# create our little application :)
app = Flask(__name__)
# Load default config and override config from an environment variable
def connect_db():
"""Connects to the specific database."""
rv = sqlite3.connect(app.config['DATABASE'])
rv.row_factory = sqlite3.Row
return rv
def init_db():
"""Initializes the database."""
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
#app.cli.command('initdb')
def initdb_command():
"""Creates the database tables."""
init_db()
print('Initialized the database.')
def get_db():
"""Opens a new database connection if there is none yet for the
current application context.
"""
if not hasattr(g, 'sqlite_db'):
g.sqlite_db = connect_db()
return g.sqlite_db
#app.teardown_appcontext
def close_db(error):
"""Closes the database again at the end of the request."""
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
#app.route('/')
def show_entries():
db = get_db()
cur = db.execute('select title, text from entries order by id desc')
entries = cur.fetchall()
return render_template('show_entries.html', entries=entries)
#app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
db = get_db()
db.execute('insert into entries (title, text) values (?, ?)',
[request.form['title'], request.form['text']])
db.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error=error)
#app.route('/logout')
def logout():
session.pop('logged_in', None)
flash('You were logged out')
return redirect(url_for('show_entries'))
#app.route("/hello")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run(host="138.165.91.210",port=5017,threaded=True)
Edit:
I'm running the app using bash:
flask --app=flaskr run
You are using an unreleased version of Flask, so keep in mind that things might change.
__name__ == '__main__' only evaluates to True when you execute a file directly (i.e., python filename.py). Since that isn't how you're running it here, it will be False and that block is skipped.
To solve your port issue, when running your application using the flask command, you need to specify your options through the command line.
python -m flask --app flaskr --host 138.165.91.210 --port 5017 --with-threads
For more information, you should check the usage
python -m flask --help
To solve your delay issue, the if __name__ == '__main__': block is important. Without it, Flask will try to run two instances of the application (once from the flask command and one from the call to app.run).
Related
I followed the tutorial at https://flask.palletsprojects.com/en/2.0.x/tutorial/factory/ and successfully created the project there. I then tried to apply this to my new project and I'm getting hung up right away. The database schema doesn't seem to get read at any point. At other points in the code I tried to print the tables and got an empty list. Here are the relevant chunks in the code where it should happen.
__init__.py:
import os
from flask import Flask
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'projectdb.sqlite')
)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(test_config)
try:
os.makedirs(app.instance_path)
except OSError:
pass
from . import db
db.init_app(app)
from . import auth
app.register_blueprint(auth.bp)
print("App created")
return app
db.py:
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
#click.command('init-db')
#with_appcontext
def init_db_command():
init_db()
click.echo('Initialized the database.')
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
auth.py:
import functools
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from werkzeug.security import check_password_hash, generate_password_hash
from ldmt.db import get_db
bp = Blueprint('auth', __name__, url_prefix='/auth')
#bp.route('/login', methods=('GET', 'POST'))
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None
user = db.execute(
'SELECT * FROM user WHERE username = ?', (username,)
).fetchone()
if user is None:
error = 'invalid username.'
elif not check_password_hash(user['password'], password):
error = 'incorrect password.'
if error is None:
session.clear()
session['user_id'] = user['id']
return redirect(url_for('index'))
flash(error)
return render_template('auth/login.html')
#bp.before_app_request
def load_logged_in_user():
user_id = session.get('user_id')
if user_id is None:
g.user = None
else:
g.user = get_db().execute(
'SELECT * FROM user WHERE id = ?', (user_id,)
).fetchone()
#bp.route('/logout')
def logout():
session.clear()
return redirect(url_for('auth.login'))
def login_required(view):
#functools.wraps(view)
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.login'))
return view(**kwargs)
return wrapped_view
schema.sql:
DROP TABLE IF EXISTS user;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
The problem happens when I try to login. Nothing has been added to the database so I expect an error that that user is not found, but the error I get is sqlite3.OperationalError: no such table: user
I can also confirm that the .sqlite file is created but empty.
You created a CLI command for flask here...
#click.command('init-db')
#with_appcontext
def init_db_command():
init_db()
click.echo('Initialized the database.')
You will have to run the command in the command line like so...
flask init-db
install the db:
pip install flask-mysqldb
create my database localy using xampp
setting the config
from flask import Flask, render_template, flash, redirect, url_for, request,
logging
from wtforms import Form, StringField, TextAreaField, validators
from flask_mysqldb import MySQL
app = Flask (__name__)
# Config MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = ''
app.config['MYSQL_DB'] = 'todo'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
# init MYSQL
mysql = MySQL(app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/add')
def task():
return render_template('add.html')
# Task Form Class
class TaskForm(Form):
name = StringField('Name', [validators.Length(min=1, max=55)])
description = TextAreaField('Description', [validators.Length(min=5)])
# Add task
#app.route('/add', methods=['GET', 'POST'])
def add():
form = TaskForm(request.form)
if request.method == 'POST' and form.validate():
name = form.name.data
description = form.description.data
# Create Cursor
cur = mysql.connection.cursor()
# Execute
cur.execute("INSERT INTO todotask(name, description) VALUES(%s, %s)",
(name, description))
# Commit to DB
mysql.connection.commit()
#Close connection
cur.close()
flash('the task created ', 'success')
return redirect(url_for('add'))
return render_template('index.html', form=form)
if __name__ == '__main__':
app.run(debug = True)
when I run the server it's working normally and give me 200 status for the post method when inserting any thing to the db but when I'm trying to check nothing insert or saved in the db , how can I make it work?
It looks like you are doing everything right, except odd way of handling routes.
Provided that:
you are running Flask in development mode with default parameters i.e. development server listens on localhost:5000,
index.html contains link to http://localhost:5000/add,
after adding you want to redirect back to http://localhost:5000.
this code should work:
from flask import Flask, render_template, flash, \
redirect, url_for, request, logging
from wtforms import Form, StringField, TextAreaField, validators
from flask_mysqldb import MySQL
app = Flask (__name__)
# Config MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = ''
app.config['MYSQL_DB'] = 'todo'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
# TODO Update secret key
app.secret_key = 'UPDATETHISPART'
# init MYSQL
# mysql = MySQL(app)
# Task Form Class
class TaskForm(Form):
name = StringField('Name', [validators.Length(min=1, max=55)])
description = TextAreaField('Description', [validators.Length(min=5)])
#app.route('/')
def index():
return render_template('index.html')
# Add task
#app.route('/add', methods=['GET', 'POST'])
def add():
form = TaskForm(request.form)
if request.method == 'POST' and form.validate():
name = form.name.data
description = form.description.data
# Create Cursor
cur = mysql.connection.cursor()
# Execute
cur.execute("INSERT INTO todotask(name, description) VALUES(%s, %s)", (name, description))
# Commit to DB
mysql.connection.commit()
# Close connection
cur.close()
flash('the task created ', 'success')
return redirect(url_for('index'))
return render_template('add.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
What I have updated:
Removed first route for /add since it seems like it is unnecessary,
Added secret key,
Reorganized how adding in /add route handles redirects/rendering.
By looking at the db insert handling, it looks just fine. Probably routes did interfere with what you intended.
Try doing it like this:
conn = mysql.connect()
cur = conn.cursor()
cur.execute("INSERT INTO todotask(name, description) VALUES(%s, %s)",
(name, description))
conn.commit()
Im writing a dummy website for class and I'm having trouble connecting my Heroku Database to my app that's local for now until I push to Heroku.
I'm not sure what the proper way to do this, and I've searched many videos/forums and I can't seem to get a straight answer from them. Ill post some of my code below. In dbconnect.py where the insert the heroku database credentials, like the URI, host, etc?
#app.py
from flask import Flask, render_template, redirect, url_for, request, session, flash
from functools import wraps
app = Flask(__name__)
app.secret_key = "Gundam"
# login required decorator
def login_required(f):
#wraps(f)
def wrap(*args, **kwargs):
if 'logged_in' in session:
return f(*args, **kwargs)
else:
flash('You need to login first.')
return redirect(url_for('login_page'))
return wrap
#app.route('/')
def homepage():
return render_template("main.html")
#app.route('/dashboard/')
#login_required
def dashboard():
return render_template("dashboard.html")
#app.errorhandler(404)
def page_not_found(e):
return render_template("404.html")
#app.route('/login/', methods=["GET", "POST"])
def login_page():
error = ''
try:
if request.method == "POST":
attempted_username = request.form['username']
attempted_password = request.form['password']
if attempted_username == "admin" and attempted_password == "password":
session['logged_in'] = True
flash('You were just logged in!')
return redirect(url_for('dashboard'))
else:
error = "Invalid Username or Password."
return render_template("login.html", error=error)
except Exception as e:
return render_template("login.html", error=error)
#app.route('/logout/')
def logout():
session.pop("logged_in", None)
return redirect(url_for('homepage'))
if __name__ == '__main__':
app.run(debug = True)
dbconnect.py
import os
import psycopg2
import urlparse
urlparse.uses_netloc.append("postgres")
url = urlparse.urlparse(os.environ[""])
conn = psycopg2.connect(
database=url.path[1:],
user=url.username,
password=url.password,
host=url.hostname,
port=url.port
)
You have to install the postgres database addon in heroku first. Run the heroku toolbelt in your computer and enter the command heroku addons:create heroku-postgresql:hobby-dev. Hobby-dev is the free version.
Once Heroku Postgres has been added a DATABASE_URL setting will be available in the app configuration and will contain the URL used to access the newly provisioned Heroku Postgres service. Use the value as your database uri. The app configuration can be accessed from your dashboard. Under settings, click Reveal config vars. You can also use the toolbelt command. See heroku config -h.
So now you can do:
url = urlparse.urlparse(os.environ["DATABASE_URL"])
For more details see https://devcenter.heroku.com/articles/heroku-postgresql
Just use the following code snippet on your python app. That should do the trick.
import os
import psycopg2
DATABASE_URL = os.environ['DATABASE_URL']
conn = psycopg2.connect(DATABASE_URL, sslmode='require')
I just finished the Flask basic tutorial (here) and even though I've done completed every step, when I am trying
python flaskr.py
what I get is a 404 Not Found error saying
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
here is the code inside the file
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
#create app
app = Flask(__name__)
app.config.from_object(__name__)
#load default conf and override config from an env var
app.config.update(dict(
DATABASE=os.path.join(app.root_path, 'flaskr.db'),
DEBUG=True,
SECRET_KEY = 'dev key',
USERNAME = 'admin',
PASSWORD = 'admin'
))
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
def connect_db():
"""connect to the specific db"""
rv = sqlite3.connect(app.config['DATABASE'])
rv.row_factory = sqlite3.Row
return rv
if __name__== '__main__':
app.run()
def get_db():
"""opens a new db connection if there is none yet for the cyrrent app"""
if not hasattr(g, 'sqlite_db'):
g.sqlite_db = connect_db()
return g.sqlite_db
#app.teardown_appcontext
def close_db(error):
"""closes the db again at the end of the request."""
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
#app.route('/')
def show_entries():
db_get_db()
cur = db.execute('select title, text from entries order by id desc')
entries = cur.fetchall()
return render_template('show_entries.html', entries=entries)
#app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
db = get_db()
db.execute('insert into entries (title, text) values (?,?)',
[request.form['title'], request.form['text']])
db.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error=error)
#app.route('/logout')
def logout():
session.pop('logged_in', None)
flash('You were logged out')
return redirect(url_for('show_entries'))
This is the console message I get (plus 3 attempts to refresh page):
user#user:~/Flask/flaskr$ python flaskr.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
127.0.0.1 - - [19/Aug/2014 15:23:40] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [19/Aug/2014 15:23:41] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [19/Aug/2014 15:23:42] "GET / HTTP/1.1" 404 -
Any suggestions on what might be going wrong?
You put your app.run() call too early:
if __name__== '__main__':
app.run()
This is executed before any of your routes are registered. Move these two lines to the end of your file.
Next, you have the first line in show_entries() is incorrect:
def show_entries():
db_get_db()
There is no db_get_db() function; this should be db = get_db() instead.
Happened to me also while following Flask Application Setup here . The error was gone after appending a trailing slash at the end of the route.
#app.route('/hello')
def hello():
return 'Hello, World!'
was changed to
#app.route('/hello/')
def hello():
return 'Hello, World!'
and the problem was solved. Hope it helps for anyone who is searching for a problem like this.
You should delete your cache and reload the page.
Press "Ctrl" + "Shift" + "i" to open the developer tools
Right-click on the "reload-icon" (⟳) located to the left of the URL bar
Select "Clear cache and refresh completely"
I have a sample web application (flask with flask-login running on heroku) at this URL: http://twittaclone.herokuapp.com.
When I run it on my localhost the login functionality works fine. When I push to heroku it freaks out and does not allow users to login (it does allow user registration). Database modifications are being made.
Why would flask login not work on heroku?
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_HOST'] = os.environ['MYSQL_DATABASE_HOST'] if 'MYSQL_DATABASE_HOST' in os.environ else config.MYSQL_DATABASE_HOST
app.config['MYSQL_DATABASE_PORT'] = os.environ['MYSQL_DATABASE_PORT'] if 'MYSQL_DATABASE_PORT' in os.environ else config.MYSQL_DATABASE_PORT
app.config['MYSQL_DATABASE_USER'] = os.environ['MYSQL_DATABASE_USER'] if 'MYSQL_DATABASE_USER' in os.environ else config.MYSQL_DATABASE_USER
app.config['MYSQL_DATABASE_PASSWORD'] = os.environ['MYSQL_DATABASE_PASSWORD'] if 'MYSQL_DATABASE_PASSWORD' in os.environ else config.MYSQL_DATABASE_PASSWORD
app.config['MYSQL_DATABASE_DB'] = os.environ['MYSQL_DATABASE_DB'] if 'MYSQL_DATABASE_DB' in os.environ else config.MYSQL_DATABASE_DB
mysql.init_app(app)
if 'SECRET_KEY' in os.environ: app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
else: app.config['SECRET_KEY'] = os.urandom(24)
def connect_db(): return mysql.connect()
###
# Routing for your application.
###
login_manager = LoginManager()
login_manager.login_view = "login"
#login_manager.user_loader
def load_user(username):
g.db = connect_db()
return get_user(username)
login_manager.init_app(app)
#app.route('/')
def home(): return render_template('home.html')
def connect_db(): return mysql.connect()
#app.before_request
def before_request():
g.user = current_user
g.db = connect_db()
#app.teardown_request
def tear_down(exception):
g.db.close()
#app.route('/main/')
#login_required
def main():
print("in main")
tweets, user = get_main()
follower_count, followee_count = get_follower_info(g.user.username)
return render_template('main.html', user=user, tweets=tweets, followercount = follower_count, followeecount = followee_count)
#app.route('/login/', methods=['GET', 'POST'])
def login():
"""Logs the user in."""
if request.method == 'GET':
if current_user is user_logged_in: logout_user()
error = None
if request.method == 'POST':
user = get_user(request.form['username'])
if user is None:
error = 'Invalid username'
elif not check_password_hash(user.password, request.form['password']):
error = 'Invalid password'
else:
flash('You were logged in')
login_user(user)
return redirect(url_for('main'))
return render_template('login.html', error=error)
Many years later but this solves your issue: Heroku gunicorn flask login is not working properly
Updated Procfile:
web: gunicorn app:app --preload
Documentation on preloading for gunicorn: https://docs.gunicorn.org/en/stable/settings.html
I'm pretty sure that Heroku uses PostgreSQL. Try referring to their documents https://devcenter.heroku.com/articles/heroku-postgresql