I'm using flask-security to handle user registration, login, etc. I'm facing a problem when registering a new user using the default flask-security views.
EDIT
I managed to advance a little on solving the problem. The initial problem was that I wasn't providing a load_user callback. Now I'm doing it:
#login_manager.user_loader
def load_user(user_id):
return User.objects.get(id=user_id)
Problem is that the confirmation url/view seems to use an AnonymousUser and so, the query filter does not match the correct user. Any clues guys?
Original
I'm able to provide user mail and password in the registration view, I successfully receive a confirmation e-mail (the default template provided by flask-security) but when I try to confirm the account clicking on the mail confirmation link I get the following attribute error:
AttributeError: 'AnonymousUserMixin' object has no attribute 'roles'
Here is the full traceback:
Traceback (most recent call last):
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site- packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_security/views.py", line 226, in confirm_email
logout_user()
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_security/utils.py", line 92, in logout_user
identity=AnonymousIdentity())
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/blinker/base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_principal.py", line 469, in _on_identity_changed
self.set_identity(identity)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_principal.py", line 418, in set_identity
self._set_thread_identity(identity)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_principal.py", line 463, in _set_thread_identity
identity=identity)
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/blinker/base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/flask_security/core.py", line 217, in _on_identity_loaded
for role in current_user.roles:
File "/home/infante/PycharmProjects/venvs/wp/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
AttributeError: 'AnonymousUserMixin' object has no attribute 'roles'
Here is my app configuration:
from flask import Flask
from flask.ext.security import MongoEngineUserDatastore, Security
from flask_login import LoginManager
from flask_mail import Mail
from wpapp.models import db, User, Role
from wpapp.views import frontend
from wpapp.configs import CONFS
login_manager = LoginManager()
app = Flask(__name__)
app.config["MONGODB_SETTINGS"] = CONFS['MONGODB_SETTINGS']
app.config["SECRET_KEY"] = CONFS['SECRET_KEY']
app.config['SECURITY_PASSWORD_HASH'] = CONFS['SECURITY_PASSWORD_HASH']
app.config['SECURITY_PASSWORD_SALT'] = CONFS['SECURITY_PASSWORD_SALT']
app.config['SECURITY_REGISTERABLE'] = CONFS['SECURITY_REGISTERABLE']
app.config['SECURITY_CONFIRMABLE'] = CONFS['SECURITY_CONFIRMABLE']
app.config['SECURITY_RECOVERABLE'] = CONFS['SECURITY_RECOVERABLE']
app.config['SECURITY_REGISTER_URL'] = CONFS['SECURITY_REGISTER_URL']
app.config['MAIL_SERVER'] = CONFS['MAIL_SERVER']
app.config['MAIL_PORT'] = CONFS['MAIL_PORT']
app.config['MAIL_USE_SSL'] = CONFS['MAIL_USE_SSL']
app.config['MAIL_USERNAME'] = CONFS['MAIL_USERNAME']
app.config['MAIL_PASSWORD'] = CONFS['MAIL_PASSWORD']
mail = Mail(app)
app.register_blueprint(frontend)
db.init_app(app)
user_datastore = MongoEngineUserDatastore(db, User, Role)
security = Security(app, user_datastore)
login_manager.init_app(app)
if __name__ == '__main__':
app.run()
And here are my models definitions (I'm using mongodb):
from flask.ext.mongoengine import MongoEngine
from flask.ext.security import UserMixin, RoleMixin
db = MongoEngine()
class Role(db.Document, RoleMixin):
name = db.StringField(verbose_name=u"Nome",
help_text=u"Inserir um nome para identificação do Papel.",
max_length=50,
required=True,
unique=True)
description = db.StringField(verbose_name=u"Descrição",
help_text=u"Inserir descrição sucinta sobre o Papel.",
max_length=255)
class User(db.Document, UserMixin):
email = db.StringField(verbose_name=u"E-mail",
help_text=u"Cadastrar um e-mail válido.",
max_length=255,
required=True,
unique=True)
password = db.StringField(verbose_name=u"Senha",
help_text=u"Cadastrar sua senha para acesso.",
required=True,
max_length=255)
active = db.BooleanField(verbose_name=u"Ativo",
help_text=u"Indica se o usuário está ativo no sistema.",
default=True)
confirmed_at = db.DateTimeField(verbose_name=u"Confirmação",
help_text=u"Horário de confirmação do usuário")
roles = db.ListField(db.ReferenceField(Role),
verbose_name=u"Papéis",
help_text=u"Atribuir papéis ao usuário.",
default=[])
Does anyone have a clue on what may the problem be?
Thanks in advance!
Thanks deadbeef404, pretty much nailed it. I would have commented on your answer, but I don't have any rep.
Actually flask login uses it's own AnonymousUserMixin class. The following snippet shows how to override it with flask security's AnonymousUser class.
login_manager = LoginManager()
from flask.ext.security import AnonymousUser
login_manager.anonymous_user = AnonymousUser
I'm not sure what your exact problem is but it seems that flask principal is trying to use the AnonymousUser (the identity in memory when no one is logged in) like an authenticated user. An AnonymousUser doesn't have a roles attribute so when it tries to access it, it throws an Exception.
Related
I'm trying to build a simple contact form with Flask and hosting it on GAE but I can't seem to get it right.
I'd truly appreciate your help because I've spent several days trying to figure this out without any success.
Here's the error I get when I click submit:
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
And here are the logs:
2022-02-14 23:03:33 default[20220215t000150] Traceback (most recent call last):
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app response = self.full_dispatch_request()
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request rv = self.handle_user_exception(e)
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request rv = self.dispatch_request()
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/srv/main.py", line 34, in contact message.send() File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/mail.py", line 1209, in send make_sync_call('mail', self._API_CALL, message, response)
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/apiproxy_stub_map.py", line 96, in MakeSyncCall return stubmap.MakeSyncCall(service, call, request, response)
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/apiproxy_stub_map.py", line 355, in MakeSyncCall rpc.CheckSuccess()
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/apiproxy_rpc.py", line 149, in CheckSuccess raise self.exception
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/runtime/default_api_stub.py", line 267, in _CaptureTrace f(**kwargs)
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/runtime/default_api_stub.py", line 260, in _SendRequest raise self._TranslateToError(parsed_response) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/runtime/default_api_stub.py", line 134, in _TranslateToError raise self._ErrorException(exception_type, msg) google.appengine.runtime.apiproxy_errors.FeatureNotEnabledError: The API call mail.Send() is currently not enabled. -- Additional details from server: App Engine APIs are not enabled, please add app_engine_apis: true to your app.yaml to enable.
Here's my main.py:
from flask import Flask, redirect, render_template, url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_talisman import Talisman
from google.appengine.api import mail, wrap_wsgi_app
app = Flask(__name__)
app.config['SECRET_KEY'] = 'my-very-very-secret-key'
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
Talisman(app)
EMAIL_ADDR = 'my_email#example.com'
class ContactForm(FlaskForm):
name = StringField(label='Name', validators=[DataRequired()])
submit = SubmitField(label='Submit')
#app.route('/')
def homepage():
return render_template('index.html')
#app.route('/contact', methods=['GET', 'POST'])
def contact():
form = ContactForm()
if form.validate_on_submit():
name = form.name.data
message = mail.EmailMessage(sender=EMAIL_ADDR,
subject='form test')
message.body = f'this is a test message from {name}'
message.to = EMAIL_ADDR
message.send()
return redirect(url_for('homepage'))
return render_template('contact.html', form=form)
if __name__ == '__main__':
app.run()
My app.yaml
runtime: python39
app_engine_apis: true
inbound_services:
- mail
- mail_bounce
My requirements.txt
Flask==2.0.2
flask-talisman==0.8.1
wtforms==3.0.0
Flask-WTF==1.0.0
appengine-python-standard>=0.3.1
I've stumbled upon the solution! If anyone else runs into this issue: 'gcloud beta app deploy' solves it. I used to deploy the app with 'gcloud app deploy' before.
I am trying to make a chat app which is linked with a database which stores the users username and password but i would like to call the username in multiple functions. I currently have a global variable which is called NAME_KEY and i would like to replace it with the username of which ever user is logged in.
Here is my code as it currently stands!
from flask import render_template, redirect, session, request, url_for, jsonify, flash, Blueprint
from .database import DataBase
from flask_mysqldb import MySQL
from flask_socketio import SocketIO
import bcrypt
import MySQLdb
from config import *
view = Blueprint("views", __name__)
# GLOBAL CONSTANTS
NAME_KEY = 'username'
MSG_LIMIT = 20
socketio = SocketIO(app) # used for user communication
db = MySQL(app)
password = b"1234"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
# VIEWS
#view.route("/login", methods=["POST", "GET"])
def login():
"""
displays main login page and handles saving name in session
:exception POST
:return: None
"""
if request.method == 'POST':
if 'username' in request.form and 'password' in request.form:
username = request.form.get('username')
password = request.form.get('password').encode("utf-8")
cursor = db.connection.cursor(MySQLdb.cursors.DictCursor)
cursor.execute("SELECT * FROM logininfo WHERE email=%s AND password=%s", (username, password))
info = cursor.fetchone()
if info is not None:
if bcrypt.checkpw(password, hashed):
session['loginsuccess'] = True
flash(f'You were successfully logged in as {username}.')
return redirect(url_for('views.home'))
else:
flash("Profile doesn't exist please try again!")
return render_template("login.html", **{"session": session})
#view.route('/new/', methods=['GET', 'POST'])
def new_user():
if request.method == "POST":
if "one" in request.form and "two" in request.form and "three" in request.form:
username = request.form['one']
email = request.form['two']
password = request.form['three']
cur = db.connection.cursor(MySQLdb.cursors.DictCursor)
cur.execute("INSERT INTO login.logininfo(name, password, email)VALUES(%s, %s, %s)",
(username, password, email))
db.connection.commit()
return redirect(url_for('login'))
return render_template("register.html")
#view.route("/logout")
def logout():
"""
logs the user out by popping username from session
:return: None
"""
session.pop(NAME_KEY, None)
flash("0You were logged out.")
return redirect(url_for("views.login"))
#view.route("/")
#view.route("/home")
def home():
"""
displays home page if logged in
:return: None
"""
if NAME_KEY not in session:
return redirect(url_for("views.login"))
return render_template("index.html", **{"session": session})
#view.route("/history")
def history():
if NAME_KEY not in session:
flash("0Please login before viewing message history")
return redirect(url_for("views.login"))
json_messages = get_history(session[NAME_KEY])
print(json_messages)
return render_template("history.html", **{"history": json_messages})
#view.route("/get_name")
def get_name():
"""
:return: a json object storing name of logged in user
"""
data = {"name": ""}
if NAME_KEY in session:
data = {"name": session[NAME_KEY]}
return jsonify(data)
#view.route("/get_messages")
def get_messages():
"""
:return: all messages stored in database
"""
db = DataBase()
msgs = db.get_all_messages(MSG_LIMIT)
messages = remove_seconds_from_messages(msgs)
return jsonify(messages)
#view.route("/get_history")
def get_history(name):
"""
:param name: str
:return: all messages by name of user
"""
db = DataBase()
msgs = db.get_messages_by_name(name)
messages = remove_seconds_from_messages(msgs)
return messages
Currently this line of code is throwing an error
'cursor = db.connection.cursor(MySQLdb.cursors.DictCursor)'
The error is as follows
"KeyError: 'MYSQL_HOST'"
I also have no idea how to go about replacing the global variable NAME_KEY with one that takes which ever user is signed up and stored in my database.
I also have a config file which is as follows
from dotenv import load_dotenv
from pathlib import Path # python3 only
import os
from flask import Flask
# set path to env file
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)
app = Flask(__name__)
class Config:
"""Set Flask configuration vars from .env file."""
# Load in environment variables
TESTING = os.getenv('TESTING')
FLASK_DEBUG = os.getenv('FLASK_DEBUG')
SECRET_KEY = os.getenv('SECRET_KEY')
SERVER = os.getenv('SERVER')
app.config["MYSQL_HOST"] = "login#localhost"
app.config["MYSQL_USER"] = "root"
app.config["MYSQL_PASSWORD"] = "pleasehelp"
app.config["MYSQL_DB"] = "login"
Any help or suggestions would be greatly appreciated.
Here are my errors
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask_socketio\__init__.py", line 46, in __call__
start_response)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\engineio\middleware.py", line 71, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\User\PycharmProjects\testApp\testApp\application\views.py", line 40, in login
cursor = db.connection.cursor(MySQLdb.cursors.DictCursor)
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask_mysqldb\__init__.py", line 94, in connection
ctx.mysql_db = self.connect
File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\flask_mysqldb\__init__.py", line 43, in connect
if current_app.config['MYSQL_HOST']:
KeyError: 'MYSQL_HOST'
I have the below code for app.py:
from flask import Flask
from flask_jwt import JWT, jwt_required, current_identity
from werkzeug.security import safe_str_cmp
class User(object):
def __init__(self, id, username, password):
self.id = id
self.username = username
self.password = password
def __str__(self):
return "User(id='%s')" % self.id
users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]
username_table = {u.username: u for u in users}
userid_table = {u.id: u for u in users}
def authenticate(username, password):
user = username_table.get(username, None)
if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
return user
def identity(payload):
user_id = payload['identity']
return userid_table.get(user_id, None)
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'super-secret'
jwt = JWT(app, authenticate, identity)
#app.route('/protected')
#jwt_required()
def protected():
return '%s' % current_identity
if __name__ == '__main__':
app.run()
When i try to make a post request to get the authentication token from Postman :
http://127.0.0.1:5000/auth
{
"username": "joe",
"password": "pass"
}
I get a peculiar error which i am not able to solve :
(flask-restful) C:\Users\bhatsubh\Projects\flask-restful>python Test.py
* Restarting with stat
* Debugger is active!
* Debugger PIN: 973-755-004
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Sep/2017 13:38:08] "POST /auth HTTP/1.1" 500 -
Traceback (most recent call last):
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1997, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1985, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\_compat.py"
, line 33, in reraise
raise value
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\_compat.py"
, line 33, in reraise
raise value
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask\app.py", li
ne 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\bhatsubh\Envs\flask-restful\lib\site-packages\flask_jwt\__init_
_.py", line 115, in _default_auth_request_handler
username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)
AttributeError: 'NoneType' object has no attribute 'get'
I have absolutely no idea what is going wrong. Can someone please help me with this?
make sure have set correct header
Content-Type:application/json
try curl for cross check
$ curl -H "Content-Type: application/json" -X POST -d '{ "username": "joe", "password": "pass" }' http://localhost:5000/auth
I suspect you’re being thrown off by this because there’s a bug in flask-jwt which is throwing up errors rather than providing proper feedback. So it’s hard to know what’s up.
If there are any header errors, it triggers errors rather than a proper response.
Dave B’s suggestion worked for me, setting the header with: Content-Type:application/json
I raised this with the developers, so hopefully, they can patch it up.
Look at https://github.com/vimalloc/flask-jwt-extended or https://github.com/vimalloc/flask-jwt-simple as alternatives to Flask-JWT. They are better designed, up to date, and still maintained (I am the author, so I am of course biased).
try this:
localhost:5000/auth
{ "username": "user1", "password": "abcxyz" }
I'm following a Flask tutorial to do authentication in my app. My user class is like so:
class User(UserMixin, db.Model): # Here we inherit from two classes
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
# Custom property getter
#property
def password(self):
raise AttributeError('password is not a readable attribute')
# Custom property setter
#password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
def __repr__(self):
return '<User %r>' % self.username
My login route is defined like so:
#auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit:
# Get a user by email and check password matches hash
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
flash('Invalid username or password')
return render_template('auth/login.html', form=form)
However when I point my browser to the /login endpoint I get the following errors:
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/app/auth/views.py", line 14, in login
if user is not None and user.verify_password(form.password.data):
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/app/models.py", line 38, in verify_password
return check_password_hash(self.password_hash, password)
File "/Users/kekearif/Documents/Python/FlaskWebDev/flasky/venv/lib/python2.7/site-packages/werkzeug/security.py", line 245, in check_password_hash
if pwhash.count('$') < 2:
AttributeError: 'NoneType' object has no attribute 'count'
Not sure what is happening here. I'm calling the endpoint from a GET (e.g. submit has not been tapped so form.validate_on_submit should be false) and there should be no password check done at all. Any ideas what I am doing wrong?
The exception is thrown because the first argument to check_password_hash() is None. In your code that means that self.password_hash is None, as that's the first argument you pass in:
return check_password_hash(self.password_hash, password)
This means that User.password = ... was never executed (generate_password_hash() can't return None). There is no password set for your user.
Give the user a password, or code defensively and handle the case where self.password_hash is set to None.
Note that your form test is always true:
if form.validate_on_submit:
because validate_on_submit is a method, not a property. Method objects are non-empty and non-zero, so true. You probably wanted to call the method:
if form.validate_on_submit():
Now the return value determines the outcome.
I am assuming you are following The Flask Mega Tutorial and have a similar code base as I.
The error described can be encountered when the 'password_hash' column for the user you are trying to login with is empty. Use the password method you have defined in the User class to set the password, then commit the changes to the database:
u = User.query.filter(User.username == 'myusername').first()
u.password('thenewpassword')
db.session.add(u)
db.session.commit()
This is my code for my main.py file which is designed to be a simple contact form built in flask.
from flask import Flask, render_template, request
from flask_mail import Mail, Message
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'YourSuperSecreteKey'
# add mail server config
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = 'YourUser#NameHere'
app.config['MAIL_PASSWORD'] = 'yourMailPassword'
mail = Mail(app)
#app.route('/')
def hello():
"""Return a friendly HTTP greeting."""
return 'Hello World!'
#app.errorhandler(404)
def page_not_found(e):
"""Return a custom 404 error."""
return 'Sorry, Nothing at this URL.', 404
#app.errorhandler(500)
def application_error(e):
"""Return a custom 500 error."""
return 'Sorry, unexpected error: {}'.format(e), 500
#app.route('/contact', methods=('GET', 'POST'))
def contact():
form = ContactForm()
if request.method == 'POST':
if form.validate() == False:
return 'Please fill in all fields <p>Try Again!!!</p>'
else:
msg = Message("Message from your visitor" + form.name.data,
sender='YourUser#NameHere',
recipients=['yourRecieve#mail.com', 'someOther#mail.com'])
msg.body = """
From: %s <%s>,
%s
""" % (form.name.data, form.email.data, form.message.data)
mail.send(msg)
return "Successfully sent message!"
elif request.method == 'GET':
return render_template('contact.html', form=form)
if __name__ == '__main__':
app.run()
I get the error: Sorry, unexpected error: 'module' object has no attribute 'SMTP_SSL'
I've called my file "main.py". Everything works fine until I try and send the actual email. Is this just because I haven't populated the settings or is something else a miss?
Sorry just figured out how to see traceback on GAE:
Exception on /contact [POST]
Traceback (most recent call last):
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/main.py", line 50, in contact
mail.send(msg)
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask_mail.py", line 491, in send
with self.connect() as connection:
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask_mail.py", line 144, in __enter__
self.host = self.configure_host()
File "/base/data/home/apps/s~smart-cove-95709/1.384663697853252774/lib/flask_mail.py", line 156, in configure_host
host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
AttributeError: 'module' object has no attribute 'SMTP_SSL'
You have set the MAIL_USE_SSL option to True:
app.config['MAIL_USE_SSL'] = True
which means that the Flask-Mail extension will want to use the smtplib.SMTP_SSL class, but that class isn't usually available on Google App Engine.
That class is only available if the Python ssl module is available, which is only the case if your Python was built with SSL support available. This isn't normally the case in the GAE environment.
The module is not available on Google App Engine unless you specifically enable it. Enable it in your app.yaml:
libraries:
- name: ssl
version: latest
Do note that the socket support on GAE is experimental.
For sending email on GAE you are better off using the mail.send_mail() function however, so you can make use of the GAE infrastructure instead.