I am working on a flask app and I was wondering if someone can help me figure out why I am getting an error as I am trying to set the DateTime when a new user is registering an account. I just want it to save the exact time that the user was registered. The following is the route that I created to add and commit the user to the database.
from flask import Flask, render_template, request, redirect, url_for, flash
from flask import escape, session
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from database import Users, Base
app.route('/registered', methods=['Get', 'POST'])
def Register():
if request.method == 'POST':
password = request.form['password']
verify = request.form['verify']
if password == verify:
newUser = Users(Username = request.form['username'],
Password = request.form['password'],
Email = request.form['email'],
DateTime = datetime.now())
session.add(newUser)
session.commit()
return redirect('HomePage')
else:
flash('Passwords do not match')
return render_template('Register.html')
And here is the database structure that I currently have setup:
class Users(Base):
__tablename__ = 'users'
Id = Column(Integer, primary_key = True)
Username = Column(String(22), unique = True, nullable = False)
Password = Column(String(22), nullable = False)
Email = Column(String(55), unique = True, nullable = False)
Registered = Column(DateTime, nullable = False)
I am not sure if the html file would have anything with setting up the datetime property.
If anyone can help. it would be much appreciated.
In the request handler, you pass a keyword argument DateTime to the Users constructor:
app.route('/registered', methods=['Get', 'POST'])
def Register():
if request.method == 'POST':
password = request.form['password']
verify = request.form['verify']
if password == verify:
newUser = Users(Username = request.form['username'],
Password = request.form['password'],
Email = request.form['email'],
DateTime = datetime.now())
But the Users model does not have a DateTime column, the correct name is Registered:
class Users(Base):
__tablename__ = 'users'
Id = Column(Integer, primary_key = True)
Username = Column(String(22), unique = True, nullable = False)
Password = Column(String(22), nullable = False)
Email = Column(String(55), unique = True, nullable = False)
Registered = Column(DateTime, nullable = False)
Related
I've created a form which takes user's name and their email address. I get this data from the form and put it into a sqlite3 database in the following way:
#app.route('/my_form', methods=["GET", "POST"])
def form_data():
if request.method == "POST":
user_name = request.form["name"]
new_user = form_database(name=user_name)
user_email = request.form["email"]
new_user_email = form_database(email=user_email)
try:
db.session.add(new_user)
db.session.add(new_user_email)
db.session.commit()
return redirect("/my_form")
Current result: each data entry gets recorded into a new row:
1|Jack||||||||||
2||svisto#hotmail.com|||||||||
Desirable result: each data entry gets recorded into the same row:
1|Jack|svisto#hotmail.com|||||||||
Question: How can I change the code such that I get the desirable result?
Lets say you have a User class in your model like this:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,
primary_key=True)
username = db.Column(db.String(32),
index=False,
unique=True,
nullable=False)
email = db.Column(db.String(64),
index=True,
unique=True,
nullable=False)
Then you can do this in your try block
try:
new_user = User(user_name=user_name,
email=email)
db.session.add(new_user)
db.session.commit()
Solution I found:
I fused:
new_user = form_database(name=user_name) and new_user_email = form_database(email=user_email)
together such that the code looks like this:
#app.route('/my_form', methods=["GET", "POST"])
def form_data():
if request.method == "POST":
user_name = request.form["name"]
user_email = request.form["email"]
new_user_details = form_database(name=user_name, email=user_email)#assigns 2 form inputs for both columns in the database model to the same variable
try:
db.session.add(new_user_details)#adds that variable to the database as one entry, hence in one row but different columns
db.session.commit()
I have started work on a project and have decided before I get too deep to get my ORM sorted out (this means going back over and re writing my classes). I believe my code is correct but I am getting a 'TypeError' whenever I try to create the database schema using Python. I load up the Python console whilst in my project directory, and type 'from app import db' which works fine. After the command 'db.create_all()' (which worked using a basic example) I am thrown the error:
'File
"C:\Users\owner\AppData\Local\Programs\Python\Python38-32\lib\site-packages\sqlalchemy\dialects\mysql\base.py",
line 2016, in visit_VARCHAR
return self._extend_string(type_, {}, "VARCHAR(%d)" % type_.length) TypeError: %d format: a number is required, not type'
I am given no clue as to where in my actual code the cause could be, and am at a total loss.
Any help would be great - a lot of code is commented out and some other code left in for now as I'm in the process of adding my ORM but it was implemented without SQLAlchemy initially. Below is my code for 'init.py':
from flask import Flask, render_template, url_for, flash, redirect, g, request, session, send_from_directory, send_file
from heychef.config import Config
from flask_sqlalchemy import SQLAlchemy
import os
import bcrypt
import uuid
import json
import ssl
from datetime import datetime
from datetime import timedelta
from heychef.models.Agency import Agency
from heychef.models.User import User
from heychef.models.Shift import Shift
from flaskext.mysql import MySQL
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
from heychef.models.Agent import Agent
#app.before_request
def before_request():
g.agent = None
g.agency = None
if 'agent' in session:
g.agent = session['agent']
if 'agency' in session:
g.agency = session['agency']
##########################################################
############# Agent Routes ################
##########################################################
#app.route("/")
def home():
return render_template('agent-views/signup.html'), 200
#app.route("/agent-signup", methods = ['POST', 'GET'])
def agentSignup():
if request.method == 'POST':
email = request.form['inputEmail']
firstName = request.form['inputFirstName']
secondName = request.form['inputSecondName']
password = request.form['inputPassword']
rPassword = request.form['inputConfirmPassword']
if(password != rPassword):
flash('Passwords do not match.', 'danger')
return render_template('agent-views/signup.html')
else:
hashedPwd = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
agent = Agent(firstName, secondName, email, hashedPwd)
agent.addAgent(self)
flash('Account created, you can log in now.', 'success')
return render_template('agent-views/signup.html')
#app.route("/agent-login", methods = ['POST','GET'])
def agentLogin():
if request.method == 'POST':
session.pop('agent', None)
email = request.form['inputEmail']
pwd = request.form['inputPassword']
connection = mysql.get_db()
cursor = connection.cursor()
result, msg = Agent.agentLogin(connection, cursor, email, pwd)
if(result):
session['agent'] = email
flash(msg, 'success')
return redirect(url_for('agentDashboard'))
else:
flash(msg, 'danger')
return render_template('agent-views/login.html')
else:
return render_template('agent-views/login.html')
#app.route("/agent-dashboard", methods = ['GET'])
def agentDashboard():
if g.agent:
return render_template('agent-views/dashboard.html'), 200
else:
msg = "Please log in"
flash(msg, 'warning')
return redirect(url_for('agentLogin'))
if __name__ == "__main__":
app.run()
and here is my Agent Class:
from heychef.models.User import User
#from heychef.models.data.AgentDb import AgentDb
from heychef import db
class Agent(db.Model):
agentId = db.Column(db.Integer, unique=True, nullable=False, primary_key=True)
firstName = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
secondName = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
email = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
level = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
agencyId = db.Column(db.Integer, unique=False, nullable=True, primary_key=False)
addressLine1 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
addressLine2 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
addressLine3 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
postcode = db.Column(db.String(20), unique=False, nullable=True, primary_key=False)
passwordHash = db.Column(db.String(256), unique=False, nullable=False, primary_key=False)
def __repr__(self):
return "<Agent(firstName='%s', lastName='%s')>" % (self.firstName, self.lastName)
def __init__(self, firstName, secondName, email, hashedPwd):
self.agentId = 1001
self.firstName = firstName
self.secondName = secondName
self.email = email
self.passwordHash = hashedPwd
#staticmethod
def agentEmailExists(cursor, email):
exists = AgentDb.agentEmailExistsDb(cursor, email)
return exists
#staticmethod
def addAgent(agent):
db.session.add(self)
db.session.commit()
#staticmethod
def agentLogin(connection, cursor, email, pwd):
failMsg = 'Email or Password does not match.'
successMsg = 'Successfully logged in.'
result = AgentDb.agentLoginDb(connection, cursor, email, pwd)
if(result):
msg = successMsg
else:
msg = failMsg
return result, msg
#staticmethod
def getWork(cursor):
work = AgentDb.getWorkDb(cursor)
return work
any help would be ace as I'm really struggling!
Many thanks
The error seems to be related to a VARCHAR (String)db column and points out that it has received a Non-Integer value ,so there might be a db.string() model field with a Non-Integer or empty parenthesis in the other model Classes in your project.
i create a simple resetful api with flask and work corrent , but after add 1 record user details , don't add next user or second user in database and give error 500.
my server is: centos 7
python: 3.7.5
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import os
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'crud.sqlite')
db = SQLAlchemy(app)
ma = Marshmallow(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True)
userid = db.Column(db.String(120), unique=True)
product = db.Column(db.String(20), unique=True)
licenses = db.Column(db.String(1000), unique=True)
def __init__(self, username, userid , product , licenses):
self.username = username
self.userid = userid
self.product = product
self.licenses = licenses
class UserSchema(ma.Schema):
class Meta:
# Fields to expose
fields = ('username', 'userid', 'product', 'licenses')
user_schema = UserSchema()
users_schema = UserSchema(many=True)
'''
Message list:
- 1x0001 = user created
- 1x0002 = user deleted
- 1x0003 = user updated
- 0x0000 = Error not found customer
- 0x0001 = Error can't add customer
- 0x0003 = Error not found customer for delete
- 0x0004 = Error can't update customer
product list:
- 2x0001 = MoeinWeb
- 2x0002 = MoeinBackup
'''
# endpoint to create new user
#app.route("/api/LicenseService/newcustomer", methods=["POST"])
def add_user():
try:
data = request.get_json()
new_user = User(username=data['username'], userid=data['userid'], product=data['product'], licenses=data['licenses'])
db.session.add(new_user)
db.session.commit()
return jsonify({'Message': '1x0001'})
except:
return jsonify({'Message': '0x0001'})
# endpoint to get user detail by id
#app.route("/api/LicenseService/customer/<userid>", methods=["GET"])
def user_detail(userid):
user = User.query.filter_by(userid=userid).first()
try:
user_data = {}
user_data['username'] = user.username
user_data['userid'] = user.userid
user_data['product'] = user.product
user_data['licenses'] = user.licenses
return jsonify(user_data)
except:
return jsonify({'Message': '0x0000'})
# endpoint to update user
#app.route("/api/LicenseService/customer/<userid>", methods=["PUT"])
def user_update(userid):
try:
user = User.query.filter_by(userid=userid).first()
username = request.json['username']
userid = request.json['userid']
product = request.json['product']
licenses = request.json['licenses']
user.username = username
user.userid = userid
user.product = product
user.licenses = licenses
db.session.commit()
return jsonify({'Message': '1x0003'})
except:
return jsonify({'Message': '0x0004'})
# endpoint to delete user
#app.route("/api/LicenseService/customer/<userid>", methods=["DELETE"])
def user_delete(userid):
try:
user = User.query.filter_by(userid=userid).first()
db.session.delete(user)
db.session.commit()
return jsonify({'Message': '1x0002'})
except:
return jsonify({'Message': '0x0003'})
if __name__ == '__main__':
app.run(host='0.0.0.0',port=7273)
just record 1 can update , delete and show with userid , but can't create record 2 on database ,
add_user()
I want to authomaticaly put name to authors blogged from loged in session.
So far I can log user but when he is already logged I cant find way to work with his name on site.
So I am trying to create some way, which will store username after he is logged in memory and flask will then use this username for blog posts and comments or editing profile. Thank you
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(64))
password = Column(String(120))
email = Column(String(64))
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
Base.metadata.create_all(engine)
Base2 = declarative_base()
class Blogpost(Base2):
__tablename__ = 'blogpost'
id = Column(Integer, primary_key=True)
title = Column(String(50))
subtitle = Column(String(50))
author = Column(String(20))
date_posted = Column(DateTime)
content = Column(Text)
def __init__(self, title, subtitle, author, date_posted, content):
self.title = title
self.subtitle = subtitle
self.author = author
self.date_posted = date_posted
self.content = content
#app.route('/login', methods=['POST'])
def login():
POST_USERNAME = str(request.form['username'])
POST_PASSWORD = str(request.form['password'])
def check_password(hashed_password, user_password):
password, salt = hashed_password.split(':')
return password == hashlib.sha256(salt.encode() + user_password.encode()).hexdigest()
Session = sessionmaker(bind=engine)
s = Session()
user = s.query(User).filter_by(username=POST_USERNAME).first()
if check_password(user.password, POST_PASSWORD) == True:
session['logged_in'] = True
user_name = POST_USERNAME
else:
flash('wrong password!')
return index()
#app.route('/add')
def add():
return render_template('add.html')
#app.route('/addpost', methods=['POST'])
def addpost():
title = request.form['title']
subtitle = request.form['subtitle']
content = request.form['content']
Session = sessionmaker(bind=engine)
session = Session()
post = Blogpost(title=title, subtitle=subtitle, author=user_name, content=content, date_posted=datetime.now())
session.add(post)
session.commit()
I would encourage you to use an extension like flask-login for user management or flask-security for extended features, meanwhile, you can store the user in flask sessions.
first import session (i will call it login_session to differentiate it with your sql-alchemy session)
from flask import session as login_session
Then once a user logs in you can store the user details like this
login_session['username'] = user.username #user here being the user object you have queried
And to access the user name from session
username = login_session['username']
and once a user logs out, you delete the user details from session like this
del login_session['username']
But as others have mentioned in the comments, for a serious web app, you will want to consider using one of the flask extensions for user management
I have a user model with functions to set and check a password using Werkzeug's set_password_hash and check_password_hash functions.
models.py
class User(db.Model):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(15), unique = True)
password = db.Column(db.String(15))
tasks = db.relationship('Task', backref='author', lazy='dynamic')
def __init__(self, username, password):
self.username = username
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)
login.py
def post(self):
username = flask.request.form['username']
passwd = flask.request.form['passwd']
user = User.query.filter_by(username = username).first()
flask.flash(user.check_password(user.password))
if user and user.check_password(user.password):
flask.session['username'] = username
else:
flask.flash("User doesn't exist or password is inccorect.")
return flask.render_template('login.html')
return flask.render_template('index.html')
The flashed result of check_password is always "False". What am I doing wrong?
You've defined User.password to have a length of 15, but the password hash is longer than 15 characters. So when you go to compare it later, it will not be the same value, it will be truncated.
The solution is to either define a longer length to accommodate the length of the hash, or use a database that doesn't care about length (PostgreSQL, SQLite) and don't set a length for the column at all (this is preferable).
password = db.Column(db.String) # no length
# or
password = db.Column(db.String(255)) # some longer length
There's also a second problem: you're calling check_password with the stored hash, not with the user input.
# wrong
user.check_password(user.password)
# should be
user.check_password(passwd)
The following is a small example that demonstrates the password working correctly.
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from werkzeug.security import generate_password_hash, check_password_hash
engine = sa.create_engine('sqlite://', echo=True)
session = Session(engine)
Base = declarative_base(engine)
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
username = sa.Column(sa.String, nullable=False, unique=True)
password = sa.Column('password', sa.String)
def set_password(self, secret):
self.password = generate_password_hash(secret)
def check_password(self, secret):
return check_password_hash(self.password, secret)
Base.metadata.create_all()
u = User(username='davidism')
u.set_password('cabbage')
session.add(u)
session.commit()
u = session.query(User).filter_by(username='davidism').one()
print(u.password)
# pbkdf2:sha1:1000$w9jx4Egp$b420d784ac6ad0575e4a9a908bb4679826e56f5f
print(u.check_password('cabbage'))
# True