I am building one website using Flask. The app.py, html template and db(postgresql) data is shown below.On hitting the URL http://127.0.0.1:5000/ we can enter the username and email. http://127.0.0.1:5000/users will show the content which is updated in db here it is Mak mak#mk.com.
app.py
from flask import Flask, render_template,request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =
'postgres://postgres:123#localhost/sample'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80))
email = db.Column(db.String(100), unique = True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' %self.username
#app.route('/')
#def index():
def index():
return render_template('add_user.html')
#app.route('/post_user', methods=['POST'])
def post_user():
user = User(request.form['username'], request.form['email'])
db.session.add(user)
db.session.commit()
return redirect(url_for('index'))
#app.route('/users')
def get_users():
users = User.query.all()
return render_template('get_user.html', user = users)
#app.route('/homepage')
def display_homepage():
return 'Display homepage'
if __name__ =='__main__':
app.run()
get_user.html
{% for singleuser in users %}
<ul>
<li>singleuser.username</li>
</ul>
{% endfor %}
Sql Schema details
1 "Mak" "mak#mak.com"
in get_users (), there's a typo in the return statement
return render_template('get_user.html', users = users)
Related
I'm trying to create a registration page where the user's username and password would get sent to a database I have set up on Heroku. I do not get any errors and after clicking the submit button I get sent to the "you are registered" page, but the username and password don't get added to the db. Here is the code:
from flask import Flask, session, render_template, request
from flask_session import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from models import *
app = Flask(__name__)
# Check for environment variable
if not os.getenv("DATABASE_URL"):
raise RuntimeError("DATABASE_URL is not set")
# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
app.config['SQLALCHEMY_ECHO'] = True
Session(app)
# Set up database
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))
db1 = SQLAlchemy(app)
class User(db1.Model):
__tablename__ = "users"
user_id = db1.Column(db1.Integer, primary_key=True,)
username = db1.Column(db1.String, nullable=False)
password = db1.Column(db1.String, nullable=False)
def add_user(self, u):
self.users.append(u)
u.user_id = self.id
with app.app_context():
db1.init_app(app)
db1.create_all()
#app.route("/", methods=['POST', 'GET'])
def main():
return render_template('main.html')
#app.route("/registered", methods=['POST'])
def registered():
username = request.form.get('rusername')
password = request.form.get('rpassword')
u1 = User(username=username, password=password)
db1.session.add(u1)
db1.session.commit()
return '<h1> You are registered! <h1>'
#app.route("/loggedin", methods=['POST'])
def loggedin():
return '<h1> You are logged in! <h1>'
Thank you for your help!
I have created a login page with wraps & functools. I have done this previously and it worked, but this time I have stored the username & password in a PostgreSQL database and queried it using the sqlalchemy flask extension.
If the correct details have been entered, it logs you into the admin page, but if you try to type on the admin page, it doesn't redirect you back to the login page.
from flask import Flask, render_template, url_for, request, redirect, flash, session
from functools import wraps
app = Flask(__name__)
app.secret_key = "pythonAkoto"
def login_required(f):
#wraps(f)
def wrap(*args, **kwargs):
if 'logged_in' in session:
return f(*args, **kwargs)
else:
flash('You need to sign in first')
return redirect(url_for('login'))
return wrap
from sqlalchemy.orm import sessionmaker, relationship
# # this part is needed to create session to query database. this should be JUST BELOW app.config..
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ForeignKey, select
meta = MetaData()
engine = create_engine("postgresql://postgres:password#localhost/db_name", echo = True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# posts database
class PostTable(Base):
__tablename__ = 'poststable'
id = Column('id', Integer, primary_key=True)
user = Column('username', String(20))
posts = Column('posts', String(30))
def __init__(self, user, posts):
self.user = user
self.posts = posts
# login database
class UserLogin(Base):
__tablename__ = 'user_login'
id = Column('id', Integer, primary_key=True)
username = Column('username', String(30))
userPW = Column('user_pw', String(20))
def __init__(self, username, user_pw):
self.username = username
self.user_pw = user_pw
Session = sessionmaker(bind=engine)
db_session = Session() # i have called this db_session to not get mixed up with sessions when logging in.
# write posts on wall
#app.route('/', methods=['GET', 'POST'])
def postpage():
title = "Posts"
name = request.form.get('name')
posts = request.form.get('posts')
if request.method == 'GET':
data = db_session.query(PostsTable).all()
flash('Write something on the wall!')
return render_template("postpage.html", title=title, data=data)
else:
db_entry = PostsTable(name, posts)
db_session.add(db_entry)
db_session.commit()
data = db_session.query(PostsTable).all()
flash(f'{name} just wrote a post!')
return render_template("postpage.html", data=data, title=title)
# login into admin page
#app.route('/login', methods=['GET', 'POST'])
def login():
title = "Login"
user = request.form.get("username")
upw = request.form.get("password")
if request.method == 'GET':
return render_template("login.html", title=title)
else:
db_user = db_session.query(UserLogin).filter(UserLogin.username==f'{user}')
db_pw = db_session.query(UserLogin).filter(UserLogin.userPW==f'{upw}')
result = db_user.first() and db_pw.first()
if result:
session['logged_in'] = True
flash(f'Hey {user}, you have just logged in!')
return redirect(url_for('admin'))
else:
error = "Invalid credentials. Please enter a valid username and/or password."
return render_template('login.html', error=error, title=title)
# admin page
#app.route('/admin')
#login_required
def admin():
title = "Admin"
return render_template("admin.html", title=title)
if __name__ == '__main__':
app.run(debug=True)
When you enter admin url, it's supposed to redirect you to the login page, but this doesn't happen; instead it takes you to the admin page without logging in!
I've done this before (without the database) and it worked fine, but this way isn't working and I can't seem to understand why.
I want to create a web framework by using Flask module. However, there is an error in my code that I couldn't solve it. This is my code:
from flask import Flask, render_template, url_for, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(200), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return '<Task %r>' % self.id
#app.route('/', methods=['POST', 'GET'])
def index():
if request.method == 'POST':
task_content = request.form['content']
new_task = Todo(content=task_content)
try:
db.session.add(new_task)
db.session.commit()
return redirect('/')
except:
return 'There was an issue adding your task'
else:
tasks = Todo.query.order_by(Todo.date_created).all()
return render_template('index.html', tasks=tasks)
#app.route('/delete/<int:id>')
def delete(id):
task_to_delete = Todo.query.get_or_404(id)
try:
db.session.delete(task_to_delete)
db.session.commit()
return redirect('/')
except:
return 'There was a problem deleting that task'
#app.route('/update/<int:id>', methods=['GET', 'POST'])
def update(id):
task = Todo.query.get_or_404(id)
if request.method == 'POST':
task.content = request.form['content']
try:
db.session.commit()
return redirect('/')
except:
return 'There was an issue updating your task'
else:
return render_template('update.html', task=task)
if __name__ == "__main__":
app.run(debug=True)
The error shown for this code is
sqlite3.OperationalError: no such table: todo
My expected web framework is I can update and delete any task on the task column. My expected web framework is:
Task Added Action
Wash dishes 2/8/2019 Delete
Update
For information, the action "Delete" and "Update" are an option to delete or update that particular task. Anyone can help me to solve this error? Thanks everyone.
You have to create table todo in file test.db
Flask/SQLAlchemy doesn't create it automatically so you have to use in code (after class Todo)
db.create_all()
But use it only once and later remove.
See official documentation for flask_sqlalchemy
I am using Flask-Security to set up user authentication for my app but I am struggling with getting the email address or ID of the currently logged in user so I can query a table with that particular users details. I've just using the standard code.
Another question here suggested the following but it didn't work:
my_user = current_user.get_id()
Standard code:
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, \
UserMixin, RoleMixin, login_required
# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
# Create database connection object
db = SQLAlchemy(app)
# Define models
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
# Create a user to test with
#app.before_first_request
def create_user():
db.create_all()
user_datastore.create_user(email='matt#nobien.net', password='password')
db.session.commit()
# Views
#app.route('/')
#login_required
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
You can use flask_login.current_user object. Its class will be what you configured Flask-Security to use to handle your users management, e.g. User for code you included.
Michael was half right, the issue is that the standard code example does not import sessions and whilst flask-security does in the back end set the session, it's not available in your flask app. This code from Michael:
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
session['email'] = request.form['email']
Whilst correct in a standard app would likely break with flask-security or at least be unnecessary as flask-security completely takes control of the /login route and handles the form securely. The only two changes needed to the flask example app are:
Changing the flask import line to:
from flask import Flask, render_template, session
This is an example of getting the user id from the session:
#app.route('/dashboard')
#login_required
def dashboard():
user_id = session["user_id"]
return name
Hope this helps someone as it took me a while to get my head around..
IMHO you can implement sessions from Flask.
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
#app.route('/')
def index():
if 'username' in session:
print("Currents user's ID is %s" % session['id']
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
session['email'] = request.form['email']
session['id'] = request.form['id']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
#app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
session.pop('email', None)
session.pop('id', None)
return redirect(url_for('index'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
See: http://flask.pocoo.org/docs/0.12/quickstart/#sessions
In flask 2.0.x user id is automaticly saved in session under _user_id, not sure how or where this changed, in the official flask docs it still uses g.user, but maybe its outdated? I couldnt get it to work for me.
The simplest way i could get it to check if a user was login in with if '_user_id' in sessions.keys(), the return value of session['_user_id'] is a string of User.id
Its better to use session for this. You can store the information is session then use it anywhere.
In your login function just store the value like:
first import the session from flask.Then use like this.
session['username'] = login_form.username.data
then use it like {{ session['username'] }} in your template.
I am Creating a Flask Application.Application is running perfectly on local server. There is no error but the data is not stored in the database. What am i Missing?
1.routes.py
from flask import Flask,render_template,request
from models import db ,User
from forms import SignupForm
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:////Database.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db. init_app(app)
app.secret_key ='development_key'
#app.route('/' , methods=['GET','POST'])
def index():
form = SignupForm() #form object
if request.method == 'POST':
if form.validate() == False:
return render_template('index.htm' , form=form)
else:
#new user to be added to database newuser = User(form.fname.data,form.lname.data,form.email.data,form.password.data)
db.create_all()
db.session.add(newuser)
db.session.commit()
return render_template('profile.htm')
elif request.method == 'GET':
return render_template('index.htm',form=form)
#app.route('/aboutus')
def aboutus():
return render_template('aboutus.htm')
#app.route('/profile')
def profile():
return render_template('profile.htm')
#app.route('/contactus')
def contactus():
return render_template('contactus.htm')
2.app.py
from routes import app
app.run(debug = True)
3.forms.py
from flask_wtf import FlaskForm as Form
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import DataRequired,Email,Length
class SignupForm(Form):
fname = StringField('First Name',validators=[DataRequired("Please Enter Your FirstName")])
lname = StringField('Last Name',validators=[DataRequired("Please Enter Your LastName")])
password = PasswordField('Password',validators=[DataRequired("Password Can't Be Empty"), Length(min=8,message="Password Must Be 8 character Long")])
email = StringField('Email',validators=[DataRequired("Please Enter Your Email") , Email("Please Enter A Valid Email")])
submit = SubmitField('Register')
4.models.py
from flask_sqlalchemy import SQLAlchemy
from werkzeug import generate_password_hash, check_password_hash
db = SQLAlchemy()
class User(db.Model):
__tablename__= "users"
id=db.Column(db.Integer,primary_key=True)
fname = db.Column(db.String(100))
lname = db.Column(db.String(100))
email = db.Column(db.String(100),unique=True)
password = db.Column(db.String(100))
def __init__(self,fname,lname,email,password):
self.fname=fname
self.lname=lname
self.email=email
self.set_password(password)
def set_password(self,password):
self.password=generate_password_hash(password)
def check_password(self,password):
return check_password_hash(self.password,password)
I tried your code. The database wasn't being created. Try something like this instead to ensure your database file is in the proper place:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'Database.db')
Do not use sqlite3 for production purpose and rather use postgresql because sqlite3 is good for local machine stuff and does not work well on the online servers as it is also does not works well on the heroku hosting platform where the database gets reset at least once in every 24 hours for which you can even check the following link https://devcenter.heroku.com/articles/sqlite3 though you did not mentioned using heroku but I am still suggesting this because heroku is very common hosting place.