Does anyone know why I'm getting this overwrite error? I only have two functions and have a single route that can't overwrite an existing endpoint function. I'm running python3 routes.py, thanks!
routes.py
from flask import request
from __init__ import app, _update_db
from models import User
from twilio.twiml.messaging_response import MessagingResponse
def _send_message(output_lines):
resp = MessagingResponse()
msg = resp.message()
msg.body("\n".join(output_lines))
return str(resp)
#app.route("/bot", methods=["POST", "GET"])
def bot():
output_lines = []
incoming_msg = request.values.get('Body', '').lower()
remote_number = request.values.get('From')
resp = MessagingResponse()
msg = resp.message()
responded = False
user = User.query.get(remote_number)
Traceback
Traceback (most recent call last):
File "routes.py", line 14, in <module>
#app.route("/bot", methods=["POST", "GET"])
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 1315, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 98, in wrapper_func
return f(self, *args, **kwargs)
File ".../Projects/wisdom/wisdom-venv/lib/python3.7/site-packages/flask/app.py", line 1284, in add_url_rule
"existing endpoint function: %s" % endpoint
AssertionError: View function mapping is overwriting an existing endpoint function: bot
Related
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'm having trouble understanding why I'm getting this error for my flask application:
I've tried debugging it and researching. It seems like my blueprints should register fine.
When I run my init_app() via wsgi.py, it seems to have trouble registering my auth_blueprint and I'm not sure why.
Error
Traceback (most recent call last):
File "F:\PROGRAMMING\pycharm_projects\home_inspection_website\Home_Inspection_Website\wsgi.py", line 4, in <module>
app = init_app()
File "F:\PROGRAMMING\pycharm_projects\home_inspection_website\Home_Inspection_Website\home_inspection_website_application\__init__.py", line 34, in init_app
app.register_blueprint(auth_blueprint)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\app.py", line 98, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\app.py", line 1168, in register_blueprint
blueprint.register(self, options, first_registration)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\blueprints.py", line 256, in register
deferred(state)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\blueprints.py", line 294, in <lambda>
self.record(lambda s: s.add_url_rule(rule, endpoint, view_func, **options))
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\blueprints.py", line 81, in add_url_rule
self.app.add_url_rule(
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\app.py", line 98, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\flask\app.py", line 1278, in add_url_rule
self.url_map.add(rule)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\werkzeug\routing.py", line 1482, in add
rule.bind(self)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\werkzeug\routing.py", line 767, in bind
self.compile()
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\werkzeug\routing.py", line 836, in compile
_build_regex(self.rule if self.is_leaf else self.rule.rstrip("/"))
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\werkzeug\routing.py", line 825, in _build_regex
convobj = self.get_converter(variable, converter, c_args, c_kwargs)
File "C:\Users\cbbgo\.virtualenvs\Home_Inspection_Website-gpy8md-i\lib\site-packages\werkzeug\routing.py", line 775, in get_converter
raise LookupError("the converter %r does not exist" % converter_name)
LookupError: the converter 'str' does not exist
Process finished with exit code 1
init.py
from flask import Flask
from extensions import asset, mongo, login_manager, csrf, bcr
from sessions.mongo_sessions import MongoSessionInterface
def init_app():
"""Initialize the core application."""
app = Flask(__name__, instance_relative_config=False)
app.config.from_object('config.DevConfig')
# app.config.from_object('config.ProdConfig')
# Initialize Plugins
asset.init_app(app)
bcr.init_app(app)
mongo.init_app(app)
login_manager.init_app(app)
csrf.init_app(app)
with app.app_context():
from assets import compile_static_assets
# Include our Routes
from auth import auth_blueprint
from errors import errors_blueprint
from inspection_home import inspection_home_blueprint
from main import main_blueprint
app.session_interface = MongoSessionInterface(db='home_inspection')
# Register Blueprints
app.register_blueprint(main_blueprint, url_prefix="/main")
app.register_blueprint(inspection_home_blueprint, url_prefix="/inspection_home")
app.register_blueprint(auth_blueprint)
app.register_blueprint(errors_blueprint)
# Create static asset bundles
compile_static_assets(app)
return app
auth blueprint
from flask import Blueprint, redirect, render_template, flash, request, url_for
from flask_login import login_required, logout_user, current_user, login_user
from forms import LoginForm
from models import User
from extensions import login_manager, mongo
import models.errors as user_errors
# Blueprint Configuration
auth_blueprint = Blueprint(
'auth',
__name__,
template_folder='views',
static_folder='static'
)
#auth_blueprint.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('inspection_home.dashboard'))
form = LoginForm()
if form.validate_on_submit():
try:
if User.login_valid(email=form.email.data, password=form.password.data):
login_user(User)
next_page = request.args.get('next')
return redirect(next_page or url_for('auth.login_successful'))
except user_errors.UserError as e:
return e.message
return redirect(url_for('auth.login'))
return render_template(
'auth.login',
form=form,
title='Log in',
template='login-page',
body='Log in with your User account.'
)
#login_manager.user_loader
def load_user(_id):
"""Check if user is logged-in on every page load."""
u = mongo.db.Users.find_one({"_id": _id})
if not u:
return None
return User(name=u['Name'],
email=u['Email'],
password=u['Password']
)
#login_manager.unauthorized_handler
def unauthorized():
"""Redirect unauthorized users to Login page."""
flash('You must be logged in to view that page.')
return redirect(url_for('auth.login'))
#auth_blueprint.route('/logout')
#login_required
def logout():
logout_user()
return redirect(url_for('main.home'))
#auth_blueprint.route('/login_successful/<str:name>')
def login_successful(name):
return render_template('login_navigation/auth/login_successful.html')
in
#auth_blueprint.route('/login_successful/<str:name>')
def login_successful(name):
return render_template('login_navigation/auth/login_successful.html')
Flaskās built-in URL converters for string is string, not str
I'm trying to send emails periodically with flask mail, but I'm stuck with this error: Flask object has no attribute app_context
def mail_periodic():
print "sending mail at " +time.ctime()
app = current_app._get_current_object()
msg = Message("no-reply: Avantgarde.Rentals",
sender="avantgarde.rentals.noreply#gmail.com",
)
msg.add_recipient('aladinne.k#gmail.com')
msg.body = 'Email periodic '
mail2 = Mail(app)
with app.app_context():
mail2.send(msg)
print"email sent "
threading.Timer(5, mail_periodic).start()
#app.route('/startcronemailing')
def startcronemailing():
try:
mail_periodic()
except Exception, exception:
return exception.message
return "crone mailing started"
the exception that i got :
Exception in thread Thread-3:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
File "app.py", line 113, in mail_periodic
host_link='http://' + request.host,
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 336, in __getattr__
return getattr(self._get_current_object(), name)
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 295, in _get_current_object
return self.__local()
File "C:\Python27\lib\site-packages\flask\globals.py", line 19, in _lookup_object
raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context
please note that even if i use another mailing service like sendgrid i got the same error
You have to pass app instance as args. If you use current_app._get_current_object() to get app instance inside target function, you will not get the right app in another thread. For example:
from threading import Thread
from flask import current_app
from flask_mail import Message
from bluelog.extensions import mail
def _send_async_mail(app, message): # target function
with app.app_context():
mail.send(message)
def send_async_mail(subject, to, html):
app = current_app._get_current_object() # get the real app instance
message = Message(subject, recipients=[to], html=html)
thr = Thread(target=_send_async_mail, args=[app, message]) # pass app
thr.start()
return thr
I have written my unitest in flask like (with in memory database);
import unittest
import json
from lobdcapi import app
from dal.dbContext import db
from models.AtgSiteToPoll import *
class TestAtgSiteToPollEP(unittest.TestCase):
def setUp(self):
app.testing = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
self.app = app.test_client()
with app.app_context():
db.init_app(app)
db.drop_all()
db.create_all()
def tearDown(self):
pass
def test_atg_sitetopoll(self):
a = AtgSiteToPoll()
a.SiteId = 1
a.IPAddress = '10.10.10.10'
a.Port = 3000
a.Category = 1
a.UserId = 'test'
a.Password = 'test123'
a.ReceiveTimeoutInMilliSeconds = 60
db.session.add(a)
db.session.commit()
assert len(AtgSiteToPoll.query.all()) is 1
When running the test I get;
Traceback (most recent call last):
File "/Users/ratha/projects/test711/ATGWS/tests/TestAtgSitesToPollEP.py", line 31, in test_atg_sitetopoll
db.session.add(a)
File "/Users/ratha/projects/test711/ATGWS/venv/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 153, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/Users/ratha/projects/test711/ATGWS/venv/lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line 1001, in __call__
return self.registry.setdefault(key, self.createfunc())
File "/Users/ratha/projects/test711/ATGWS/venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2939, in __call__
return self.class_(**local_kw)
File "/Users/ratha/projects/test711/ATGWS/venv/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 141, in __init__
self.app = app = db.get_app()
File "/Users/ratha/projects/test711/ATGWS/venv/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 912, in get_app
'No application found. Either work inside a view function or push'
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
What Im doing wrong here?
I am trying to implement Google Oauth 2.0 login for my tornado app. They have made some changes with 3.2.2 and they do not seem to have clear instructions. Following is my code:
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
user = self.get_secure_cookie('trakr')
if not user: return None
return True
class ProductsHandler(BaseHandler):
#tornado.web.authenticated
def get(self):
self.render("products.html")
return
class GAuthLoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
#tornado.gen.coroutine
def get(self):
if self.get_current_user():
self.redirect('/products')
return
if self.get_argument('code', False):
user = yield self.get_authenticated_user(redirect_uri=settings.google_redirect_url,
code=self.get_argument('code'))
if not user:
self.clear_all_cookies()
raise tornado.web.HTTPError(500, 'Google authentication failed')
access_token = str(user['access_token'])
http_client = self.get_auth_http_client()
http_client.fetch('https://www.googleapis.com/oauth2/v1/userinfo?access_token='+access_token, self._save_user_profile)
return
elif self.get_secure_cookie('trakr'):
self.redirect('/products')
return
else:
yield self.authorize_redirect(
redirect_uri=settings.google_redirect_url,
client_id=self.settings['google_oauth']['key'],
scope=['email'],
response_type='code',
extra_params={'approval_prompt': 'auto'})
def _save_user_profile(self, response):
if not response:
raise tornado.web.HTTPError(500, "Google authentication failed.")
user = json.loads(response.body)
self.set_secure_cookie('trakr', user['email'])
self.redirect('/products')
Currently I am getting following error:
[E 140702 12:35:30 ioloop:491] Exception in callback <functools.partial object at 0xa51ff54>
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 477, in _run_callback
callback()
File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 331, in wrapped
raise_exc_info(exc)
File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 302, in wrapped
ret = fn(*args, **kwargs)
File "main.py", line 202, in _save_user_profile
self.redirect('/')
File "/usr/local/lib/python2.7/dist-packages/tornado/web.py", line 629, in redirect
raise Exception("Cannot redirect after headers have been written")
Exception: Cannot redirect after headers have been written
I don't understand where I am setting the response headers.
How to fix this issue?
I am doing this right way? Do you have any example code?
If anyone is looking, here is the script after Ben's answer:
class GAuthLoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
#tornado.gen.coroutine
def get(self):
if self.get_current_user():
self.redirect('/products')
return
if self.get_argument('code', False):
user = yield self.get_authenticated_user(redirect_uri=settings.google_redirect_url,
code=self.get_argument('code'))
if not user:
self.clear_all_cookies()
raise tornado.web.HTTPError(500, 'Google authentication failed')
access_token = str(user['access_token'])
http_client = self.get_auth_http_client()
response = yield http_client.fetch('https://www.googleapis.com/oauth2/v1/userinfo?access_token='+access_token)
if not response:
self.clear_all_cookies()
raise tornado.web.HTTPError(500, 'Google authentication failed')
user = json.loads(response.body)
# save user here, save to cookie or database
self.set_secure_cookie('trakr', user['email'])
self.redirect('/products')
return
elif self.get_secure_cookie('trakr'):
self.redirect('/products')
return
else:
yield self.authorize_redirect(
redirect_uri=settings.google_redirect_url,
client_id=self.settings['google_oauth']['key'],
scope=['email'],
response_type='code',
extra_params={'approval_prompt': 'auto'})
Don't mix coroutine and callback styles. The http_client.fetch call at the end of the if self.get_argument('code') block should use a yield and no callback argument (and then inline the _save_user_profile method before the return)