Testing out an apps.py in my environment project directory, this is my script for a login/register form:
#app.py
from flask import Flask, request, session, redirect, url_for, render_template, flash
from django.apps import AppConfig
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import psycopg2 #pip install psycopg2
import psycopg2.extras
import re
from werkzeug.security import generate_password_hash, check_password_hash
#
class IndexConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'index'
#
app = Flask(__name__)
app.secret_key = 'cairocoders-ednalan'
DB_HOST = "localhost"
DB_NAME = "users"
DB_USER = "postgres"
DB_PASS = "admin"
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)
#app.route('/')
def home():
# Check if user is loggedin
if 'loggedin' in session:
# User is loggedin show them the home page
return render_template('home.html', username=session['username'])
# User is not loggedin redirect to login page
return redirect(url_for('login'))
#app.route('/login/', methods=['GET', 'POST'])
def login():
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
# 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:
username = request.form['username']
password = request.form['password']
print(password)
# Check if account exists using MySQL
cursor.execute('SELECT * FROM users WHERE username = %s', (username,))
# Fetch one record and return result
account = cursor.fetchone()
if account:
password_rs = account['password']
print(password_rs)
# If account exists in users table in out database
if check_password_hash(password_rs, password):
# 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('home'))
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
return render_template('login.html')
#app.route('/register', methods=['GET', 'POST'])
def register():
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
# Check if "username", "password" and "email" POST requests exist (user submitted form)
if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'email' in request.form:
# Create variables for easy access
fullname = request.form['fullname']
username = request.form['username']
password = request.form['password']
email = request.form['email']
_hashed_password = generate_password_hash(password)
#Check if account exists using MySQL
cursor.execute('SELECT * FROM users WHERE username = %s', (username,))
account = cursor.fetchone()
print(account)
# If account exists show error and validation checks
if account:
flash('Account already exists!')
elif not re.match(r'[^#]+#[^#]+\.[^#]+', email):
flash('Invalid email address!')
elif not re.match(r'[A-Za-z0-9]+', username):
flash('Username must contain only characters and numbers!')
elif not username or not password or not email:
flash('Please fill out the form!')
else:
# Account doesnt exists and the form data is valid, now insert new account into users table
cursor.execute("INSERT INTO users (fullname, username, password, email) VALUES (%s,%s,%s,%s)", (fullname, username, _hashed_password, email))
conn.commit()
flash('You have successfully registered!')
elif request.method == 'POST':
# Form is empty... (no POST data)
flash('Please fill out the form!')
# Show registration form with message (if any)
return render_template('register.html')
#app.route('/logout')
def logout():
# Remove session data, this will log the user out
session.pop('loggedin', None)
session.pop('id', None)
session.pop('username', None)
# Redirect to login page
return redirect(url_for('login'))
#app.route('/profile')
def profile():
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
# Check if user is loggedin
if 'loggedin' in session:
cursor.execute('SELECT * FROM users WHERE id = %s', [session['id']])
account = cursor.fetchone()
# Show the profile page with account info
return render_template('profile.html', account=account)
# User is not loggedin redirect to login page
return redirect(url_for('login'))
if __name__ == "__main__":
app.run(debug=True)
This is the error I receive when I run 'flask run' in the terminal, not sure what it means at all.
What I'm trying to achieve is connecting psql database to my website and using flask as the web framework
PS C:\Users\sefni\Documents\test_django_app\Environments\testProject> flask run
flask : The term 'flask' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ flask run
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (flask:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Either you have not installed flask. You should do:
pip install flask
Or you are not running the application correctly. You run like this (from the directory where your code is):
python -m flask run
You can run the app using app.run() in your case you need to execute python app.py
but If you want it to run using flask run then you need to set the env
executing the two commands.
set FLASK_APP=application.py
set FLASK_DEBUG=1
now you can run the app using the below line
flask run
if you are using bash then use export in place of set. here for reference
Related
I've created a Python Flask site with a login form and a signup form. Both of these are working and when a user signs up, their email, name and password (sha256 hashed) are stored in a sqlite database. I now need to use the flask_change_password library to create a form that will allow users to change their password and I'm just struggling on this.
First, I'm using PyCharm and installed flask-change-password for my env but when I add this line from flask_change_password import ChangePassword, I get:
from flask_change_password import ChangePassword
ModuleNotFoundError: No module named 'flask_change_password'
I don't understand this because I did install it in my env. I also tried installing with pip pip install flask-change-password to resolve the error without success.
My second problem is that I don't know where I should implement or how to implement the change_password form or how to change a certain password for a specific user.
This is my auth code for signup and login:
from flask import Blueprint, render_template, redirect, url_for, request, flash
from flask_change_password import ChangePasswordForm
from flask_login import login_user, login_required, logout_user
from sqlalchemy.sql.functions import current_user
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User
from . import db
auth = Blueprint('auth', __name__)
#auth.route('/login')
def login():
return render_template('login.html')
#auth.route('/signup')
def signup():
return render_template('signup.html')
#auth.route('/signup', methods=['POST'])
def signup_post():
email = request.form.get('email')
name = request.form.get('name')
password = request.form.get('password')
user = User.query.filter_by(email=email).first() # check to see if user already exists
if user: # if a user is found, we want to redirect back to signup page so user can try again
flash('email address already exists. please login with your email.')
return redirect(url_for('auth.signup'))
new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))
# add the new user to the database
db.session.add(new_user)
db.session.commit()
return redirect(url_for('auth.login'))
#auth.route('/login', methods=['POST'])
def login_post():
email = request.form.get('email')
password = request.form.get('password')
remember = True if request.form.get('remember') else False
user = User.query.filter_by(email=email).first()
if not user or not check_password_hash(user.password, password):
flash('Please check your login details and try again.')
return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page
login_user(user, remember=remember)
return redirect(url_for('main.profile'))
#auth.route('/logout')
#login_required
def logout():
logout_user()
return render_template('goodbye.html')
My init code:
from flask_sqlalchemy import SQLAlchemy
from flask_change_password import ChangePassword
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'UMGC-SDEV300-Key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
# app.secret_key = os.urandom(20)
# flask_change_password = ChangePassword(min_password_length=10, rules=dict(long_password_override=2))
# flask_change_password.init_app(app)
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import User
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
As you can see, I'm importing the flask_change_password module ChangePasswordForm but It fails to import??
I ended up fixing this issue by removing flask from the default instance of pip3. I also removed flask-security from the default instance of pip3. I then reinstalled each of these modules in the venv and everything worked.
I'm building a very simple Flask application, when I implemented load_user from flask-login, I started having errors because the function was getting None passed to it and was trying to query using a None value.
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
#login_manager.user_loader
def load_user(id):
return User.query.get(id)
Possibly relevant files:
auth/__init__.py:
from flask import Blueprint
auth = Blueprint('auth', __name__, url_prefix='/auth')
from . import views
auth/views.py:
from flask import render_template, redirect, url_for, flash, session
from flask_login import login_user
from app.forms import LoginForm
from app.models import User
from app.queries import get_user
from . import auth
#auth.route('/login', methods=['GET', 'POST'])
def login():
login_form = LoginForm()
context = {
'login_form' : login_form
}
username = login_form.username.data
password = login_form.password.data
if login_form.validate_on_submit():
user_query = get_user(username)
if user_query:
db_password = user_query.password
if password == db_password:
registeredUser = User(username = username,
password = password)
login_user(registeredUser)
flash('Bienvenido de nuevo!', 'alert alert-success alert-dismissible')
return redirect(url_for('hello'))
else:
flash('La informaciĆ³n no coincide', 'alert alert-danger')
else:
flash('El usuario no existe.', 'alert alert-danger')
return redirect(url_for('index'))
return render_template('login.html', **context)
I'm not using the username as the primary key, I have a separate id column for that.
Assuming, from context, that user_query = get_user(username) is actually a User object and not a query, making a new User and passing it to login_user before persisting it mean that its id will be be None.
The easy fix would be to replace
if password == db_password:
registeredUser = User(username = username,
password = password)
login_user(registeredUser)
with
if password == user_query.password:
login_user(user_query)
and then to consider renaming user_query to user so that the code is clearer.
Also, give some thought to not storing user password in the clear. The Flask Mega Tutorial has a chapter that'll walk you through a way to store passwords encrypted.
I am trying to create a login page which verifies the users directly from an SQL DB. I have used session as below:
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
#app.route('/login', methods=['GET', 'POST'])
def login():
username = request.form['username']
password = request.form['password']
session['username'] = username
# db.verify authenticates user from SQL DB
verifiedUser = db.verifyUser(username, password)
if verifiedUser:
session['logged_in'] = True
global currentUser
currentUser = session['username']
return redirect(url_for('home'))
else:
errormsg = "wrong password"
flash(errormsg)
print(errormsg)
return render_template('login.html', error=errormsg)
#app.route('/logout')
def logout():
# Remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('login'))
But with this approach, two users with names "Jack" and "Jill" log in from two different machines, the system overrides and only takes one user.
I have looked at flask-login, but I do not have a user model in my application as I am using an SQL DB directly to verify the username and password. https://flask-login.readthedocs.io/en/latest/
Can anyone provide an example or any other to implement sessions to handle multiple users in Python?
app = Flask(__name__)
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
db = firebase.database()
#app.route('/login', methods=["POST", "GET"])
def login():
message = ""
if request.method == "POST":
email = request.form["login_email"]
password = request.form["login_password"]
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
user_id = user['idToken']
return redirect(url_for('admin'))
except:
message = "Incorrect Password!"
return render_template("login.html", message=message)
#app.route('/admin')
def admin():
return render_template("admin.html")
if __name__ == '__main__':
app.run()
How can I only load /admin page when the user is logged in? I know it has something to do with the user token, but I'm still not sure about how I could use the token to identify whether the user is logged in or not. Also, the user and user_id are not defined in admin()and only in login() since they're in a function.
So what do I need to change in my code in order to only load the /admin page when the user is logged in?
use flask session to store your key,if key exist then user is logged,
also you can access all session variables globally for individual session
from flask import Flask, session, request
import requests
import os
app = Flask(__name__)
app.secret_key = os.urandom(24)
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
db = firebase.database()
#app.route('/login', methods=["POST", "GET"])
def login():
message = ""
try:
print(session['usr'])
return redirect(url_for('admin'))
except KeyError:
if request.method == "POST":
email = request.form["login_email"]
password = request.form["login_password"]
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
user_id = user['idToken']
session['usr'] = user_id
return redirect(url_for('admin'))
except:
message = "Incorrect Password!"
return render_template("login.html", message=message)
#app.route('/admin')
def admin():
try:
print(session['usr'])
return render_template("admin.html")
except KeyError:
return redirect(url_for('login'))
if __name__ == '__main__':
app.run()
if session['usr'] is not assigned then it will give key error which means that usr in not logged in. but note that in the process of logout you need to delete the session for that usr.
I am trying to connect my FLASK app with MySQL on localhost(127.0.0.1:5000) but getting below error.
super(Connection, self).__init__(*args, **kwargs2)
_mysql_exceptions.OperationalError: (2013, "Lost connection to MySQL server at 'waiting for initial communication packet', system error: 60")
I am using "flask_mysqldb" library. When i tried to fill form and hit submit. it tries to connect to db but never got success and returns error.
Please check out my code and help.
from flask import Flask, render_template, flash, redirect, url_for, request, session, logging
from data import Articles
from flask_mysqldb import MySQL
from wtforms import Form, StringField, TextAreaField, PasswordField, validators
from passlib.hash import sha256_crypt
app = Flask("__name__")
# config MySQL
app.config["MYSQL_HOST"] = "127.0.0.1"
app.config["MYSQL_PORT"] = 5000
app.config["MYSQL_USER"] = "root"
app.config["MYSQL_DB"] = "myflaskapp"
app.config["MYSQL_CURSORCLASS"] = "DictCursor"
# init MySQL
mysql = MySQL(app)
Articles = Articles()
#app.route("/")
def index():
return render_template("index.html")
#app.route("/about")
def about():
return render_template("about.html")
#app.route("/articles")
def articles():
return render_template("articles.html", articles = Articles)
#app.route("/article/<string:id>/")
def article(id):
return render_template("article.html", id=id)
# collect and validate user data
class RegisterForm(Form):
name = StringField('Name', [validators.Length(min=1, max=50)])
username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email', [validators.Length(min=6, max=50)])
password = PasswordField('Password', [
validators.DataRequired(),
validators.EqualTo('confirm', message='Password do not match')
])
confirm = PasswordField('Confirm Password')
# insert user data to DB
#app.route("/register", methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if request.method == 'POST' and form.validate():
name = form.name.data
email = form.email.data
username = form.username.data
password = sha256_crypt.encrypt(str(form.password.data))
# create cursor(handler) to connect DB
cur = mysql.connection.cursor()
cur.execute("INSERT INTO users(name, email, username, password) VALUES (%s, %s, %s, %s)", (name, email, username, password))
# commit to db
mysql.connection.commit()
# close the connection
cur.close()
flash('You are now Registered', 'success')
return redirect(url_for('index'))
return render_template('register.html', form=form)
if __name__ == "__main__":
app.run(debug=True)
Below are the versions i am using.
Python: 3.6
MySQL: 5.7.21
Q: Is "flask_mysqldb" support python 3.6 or not?
Q: What is the good alternative, if required?
PyMySQL
mysqlclient
SQLalchemy
And yes, mysqlclient is also installed already.
Here are some of these troubleshoots you can try (these are independent steps: So try (1), check if it works, try (2), check if it works and so on...) -
Try localhost instead of 127.0.0.1 (thats it!)
Setting bind-address = 0.0.0.0 in mysql/my.cnf. It basically listens to all addresses (but still one port) then.
And don't forget restart your server: systemctl restart mysql
Database directory read-write permission. Just make sure your application is able to rw files on db location. Try chmod 777 for testing.
Let me know if any of this works. If it doesn't, post the error and we can try something.
Note: It is a database level problem not a python problem. Check this mysql forum thread for more clues.