I’m trying to get data from postgressql through SQLAlchemy and loop items in to a html page.
I’m doing something wrong but I can’t finger it out.
config.py
import connexion
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
connex_app = connexion.App(__name__)
# Get the underlying Flask app instance
app = connex_app.app
# Configure the SqlAlchemy part of the app instance
app.config["SQLALCHEMY_ECHO"] = True
app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://hey:hey2#localhost/heys"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# Create the SqlAlchemy db instance
db = SQLAlchemy(app)
# Initialize Marshmallow
ma = Marshmallow(app)
models.py
from config import db, ma
from sqlalchemy import Column, Integer, String
class types(db.Model):
__tablename__='types'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
class TypesSchema(ma.ModelSchema):
class Meta:
model = types
sqla_session = db.session
types.py
from flask import make_response, abort
from config import db
from models import types, TypesSchema
def all_types():
# Create the list of wine type from our data
types = types.query.order_by(types.id).all()
# Serialize the data for the response
types_schema = TypesSchema(many=True)
data = types_schema.dump(types).data
return data
app.py
from flask import render_template
import json
# local modules
import config
# Get the application instance
connex_app = config.connex_app
# create a URL route in our application for "/"
#connex_app.route("/")
def all_types():
return render_template("index.html", types=all_types)
if __name__ == "__main__":
connex_app.run(debug=True)
index.html
...
<tbody>
{% for type in types %}
<h1>Name: {{type.name}}</h1>
<h2>ID: {{type.id}}</h2>
{% endfor %}
</tbody>
...
The return from types.py gives
[{'id': 1, 'name': 'Red wine'}, {'id': 2, 'name': 'White wine'}, {'id': 3, 'name': 'Sparkling'}, {'id': 4, 'name': 'Rosé'}, {'id': 7, 'name': 'Sweet Wine'}, {'id': 24, 'name': 'Tawny'}, {'id': 25, 'name': 'Not Classified'}]
But when I run it, I get "TypeError: 'function' object is not iterable".
What I'm doing wrong?
Traceback update
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/2/Library/Python/3.7/lib/python/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/2/Desktop/Python/Vino_app/app.py", line 23, in all_types
return render_template("index.html", types=types.all_types())
AttributeError: module 'types' has no attribute 'all_types'
You have two things called all_types here - your handler and your utility function - which is confusing. But in fact you're not actually calling either of them. What you're doing is passing a reference to the current handler function into your template, which naturally doesn't know what to do with it.
You need to import your types module into your apps.py and then pass the result of calling the function:
import types
...
#connex_app.route("/")
def all_types():
return render_template("index.html", types=types.all_types())
Related
I have a Flask-SQLAlchemy association table named 'followers' and when I run the query following query via REPL it runs fine, but when running the code on the Flask application it gives me the error "'AttributeError: 'function' object has no attribute 'c'".
Function calling the query
#app.route('/following/<int:user_id>', methods=['GET'])
#login_required
def following(user_id):
"""
Show all the Tutors the user is following
"""
user = Users.query.get(user_id)
page = request.args.get('page', 1, type=int)
result = db.session.query(Users, Tutors)\
.join(Tutors, Tutors.user_id==Users.id ,full=True)\
.join(followers, Tutors.id == followers.c.followed_id)\
.filter(user_id==followers.c.follower_id).all()
next_url = url_for('index', page=result.next_num) if result.has_next else None
prev_url = url_for('index', page=result.prev_num) if result.has_prev else None
data = {}
data['user'] = []
data['tutor'] = []
rows = len(result.items)
for i in range(rows):
data['user'].append(result.items[i][0])
data['tutor'].append(result.items[i][1])
return render_template('index.html', title='Following',
data=data, rows=rows,
next_url=next_url, prev_url=prev_url)
Just the query
result = db.session.query(Users, Tutors)\
.join(Tutors, Tutors.user_id==Users.id ,full=True)\
.join(followers, Tutors.id == followers.c.followed_id)\
.filter(user_id==followers.c.follower_id).all()
Models
followers = db.Table('followers',
db.Column('follower_id', db.Integer, db.ForeignKey('users.id')),
db.Column('followed_id', db.Integer, db.ForeignKey('tutors.id'))
)
class Users(UserMixin, db.Model):
__tablename__ = 'users'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
... (other non-related properties)
followed = db.relationship('Tutors', secondary=followers, lazy='dynamic',
backref=db.backref('followers', lazy='dynamic'))
class Tutors(db.Model):
__tablename__ = 'tutors'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
... (other non-related properties)
Error traceback
Error on request:
Traceback (most recent call last):
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/werkzeug/serving.py", line 323, in run_wsgi
execute(self.server.app)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/werkzeug/serving.py", line 312, in execute
application_iter = app(environ, start_response)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask_login/utils.py", line 272, in decorated_view
return func(*args, **kwargs)
File "/Users/richardnienkotter/Documents/Projects/codetutors/app/routes.py", line 134, in following
result = db.session.query(Users, Tutors, followers.c.follower_id, followers.c.followed_id)\
AttributeError: 'function' object has no attribute 'c'
Using type() on the Debug Console shows that 'followers' is a function and that's the root of the problem, but why is it being called as a function?
Solution
In routes.py I had the same name for both the view function and the association table, which was causing the problem.
Thanks Abhi for the help :)
please check the file named
"/Users/richardnienkotter/Documents/Projects/codetutors/app/routes.py", line 134, in following
There may be a function named as followers, which is contradicting with your table named as followers.
I am getting this error: AttributeError: 'Request' object has no attribute 'sid' when using socketio in flask. Here is the output:
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/user/tennisprogram/application.py", line 34, in create_game_post
join_room(str(gameid))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_socketio/__init__.py", line 865, in join_room
sid = sid or flask.request.sid
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
AttributeError: 'Request' object has no attribute 'sid'
Here is the code I'm using. If you need something other than the backend please let me know and I'd be happy to include it :).
Input:
from flask import Flask, redirect, request, render_template, session, url_for
from flask_socketio import SocketIO, emit, join_room, leave_room, close_room
app = Flask(__name__)
socket = SocketIO(app)
app.config["SECRET_KEY"] = 'secret-key'
games = [None, None, None, None, None, None, None, None, None, None]
class Game:
def __init__(self, player1, player2, id):
self.id = id
self.infodictionary = {"player1_name":player1, "player1_score":["0", "0", "0"], "player2_name":player2, "player2_score":["0", "0", "0"]}
#app.route("/")
def index():
return render_template("index.html")
#app.route("/create_game")
def create_game():
return render_template("create_game.html")
#app.route("/create_game/post", methods=["POST"])
def create_game_post():
if "host" in session:
return "Already hosting a game" #Handle later
for gameid, game in enumerate(games):
if game == None:
game = Game(request.form.get("player1"), request.form.get("player2"), gameid)
games[gameid] = game
session["host"] = gameid
return redirect(url_for('game', id=game.id))
return "No game slot available" #Handle later
#app.route("/game/<id>")
def game(id):
join_room(str(id))
if int(id) == session["host"]:
return render_template("score.html", host=True, game=games[int(id)])
else:
return render_template("score.html", host=False, game=games[int(id)])
#socket.on("host-update")
def update(data):
p1 = data["player1_score"]
p2 = data["player2_score"]
games[int(data["id"])].infodictionary["player1_score"] = p1
games[int(data["id"])].infodictionary["player2_score"] = p2
emit("update", {"player1_score":p1, "player2_score":p2}, room=data["id"])
#Handling join game
'''
#socket.on("joingame")
def join(data):
r = data["room"]
join_room(r)
'''
#app.route("/join_game")
def join_game():
return render_template("join_game.html")
#join_game.html will redirect user to join_game_post. The socket will activate in join_game.html
#app.route("/join_game/join", methods=["POST"])
def join_game_post():
id = request.form.get("id")
return redirect(url_for("game", id=id))
#app.route("/del")
def delete_host():
games[int(session["host"])] = None
del session["host"]
Referring to the answer here about AttributeError: 'Request' object has no attribute 'sid'
I believe that your error maybe caused by this line
*emit("update", {"player1_score":p1, "player2_score":p2}, room=data["id"])
Quoting the reason from the source above
emit() function has a default of emitting to the sender of an originating event. This default only makes sense when you call the function from an event handler. You are calling it from a route, which does not have the Socket.IO context (in particular, request.sid).
Do you know to which user(s) you want to emit an event from this
route? If you want to emit to all your connected clients, add
broadcast=True. If you know the sid of the user you want to address,
then add room=sid. You also need to specify the namespace, so add
namespace='/' or use the proper namespace name.
The error could also be as simple as, user has been disconnected before being routed/redirected.
I'm getting this error even I am to render the template. I tried changing the function names also.
This is happening due to flask(error) I think
Traceback (most recent call last):
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 2463, in call
return self.wsgi_app(environ, start_response)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functionsrule.endpoint
File "/Users/ayyagari/Documents/DeepNews/web_2/website/main.py", line 57, in register_user
return render_template(url_for('main.register_form'))
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/templating.py", line 138, in render_template
ctx.app.jinja_env.get_or_select_template(template_name_or_list),
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/jinja2/environment.py", line 869, in get_or_select_template
return self.get_template(template_name_or_list, parent, globals)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/jinja2/environment.py", line 830, in get_template
return self._load_template(name, self.make_globals(globals))
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/jinja2/environment.py", line 804, in _load_template
template = self.loader.load(self, name, globals)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/jinja2/loaders.py", line 113, in load
source, filename, uptodate = self.get_source(environment, name)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/templating.py", line 60, in get_source
return self._get_source_fast(environment, template)
File "/Users/ayyagari/Documents/DeepNews/web_2/venv/lib/python3.7/site-packages/flask/templating.py", line 89, in _get_source_fast
raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: /register
Here is my code
from flask import (
Blueprint, redirect, render_template, request, url_for,
flash)
from website.db import get_db
bp = Blueprint('main', __name__)
#bp.route('/home')
def index():
return render_template("index.html")
#bp.route('/register')
def register_form():
return render_template("form.html")
#bp.route('/success')
def success():
return render_template("response.html")
#bp.route('/register_user', methods=["POST"])
def register_user():
if request.method == 'POST':
email_id = request.form['reg-email']
company = request.form['reg-company']
type_of_business = request.form['industry_type']
checkbox = request.form['reg-check']
db = get_db()
error = None
if not email_id:
error = 'Email ID is required.'
elif not company:
error = 'Company is required.'
elif not type_of_business:
error = 'Type of Business is required.'
elif not checkbox:
error = 'Accept the Terms and Conditions'
elif db.execute(
'SELECT id FROM beta_users WHERE email_id = ?', (email_id,)
).fetchone() is not None:
error = 'User {} is already registered.'.format(email_id)
if error is None:
db.execute(
'INSERT INTO beta_users (email_id, company, type_of_org, checkbox) VALUES (?, ?, ?, ?)',
(email_id, company, type_of_business, checkbox)
)
db.commit()
return redirect(url_for('main.success'))
flash(error)
return render_template(url_for('main.register_form'))
#bp.route('/error')
def errors():
return render_template("404.html")
API is also showing a 500 Internal server error
The problem is here:
return render_template(url_for('main.register_form'))
url_for returns a url to access the route via the Internet, which isn't what render_template uses. render_template is expecting a html/text file.
So, either replace that either with:
return render_template('register.html')
Or redirect the user to the other route, to let it do it's work:
from flask import redirect
...
return redirect(url_for('main.register'))
Trying to add a custom batch action but I keep getting this error, I've added my imports into the code to show what i'm importing, this file is separate to my model file, this is my views.py file
Views.py
import flask_admin as admin
import textwrap
from flask_admin.actions import action
from flask_admin.contrib import sqla
from flask_admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla.filters import FilterEqual
from app.models import FileRegister, FileRegisterStatus
from app import app, db, models
class PageView(ModelView):
#action("active", "Active", 'Are you sure you want to active selected pages?')
def action_active(self, ids):
try:
query = Page.query.filter(Page.id.in_(ids))
count = 0
for page in query.all():
page.is_active = True
count += 1
flash(ngettext('Page was successfully activated.',
'%(count)s pages were successfully activated.',
count,
count=count))
except Exception as ex:
if not self.handle_view_exception(ex):
raise
flash(gettext('Failed to active pages. %(error)s', error=str(ex)), 'error')
models.py
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Boolean, TIMESTAMP, ForeignKey
import datetime
Base = declarative_base()
class Page(Base):
__tablename__ = 'page'
id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
page_name= Column(String(500), index=True, nullable=False)
is_page_active= Column(Boolean())
def __init__(self, page_name, is_page_active):
self.page_name= page_name
self.is_page_active= is_page_active
def __unicode__(self):
return self.page_name
This is the Traceback (most recent call last) I get after running the code, ,I think its because I call query() on my mapped classes instead of the session?
Traceback (most recent call last):
File "C:\page\env\lib\site-packages\flask\app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "C:\page\env\lib\site-packages\flask\app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "C:\page\env\lib\site-packages\flask\app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\page\env\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\page\env\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\page\env\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\page\env\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\page\env\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\page\flask_admin\base.py", line 69, in inner
return self._run_view(f, *args, **kwargs)
File "C:\page\flask_admin\base.py", line 368, in _run_view
return fn(self, *args, **kwargs)
File "c:\page\flask_admin\model\base.py", line 2145, in action_view
return self.handle_action()
File "C:\page\flask_admin\actions.py", line 117, in handle_action
response = handler[0](ids)
File "C:\page\app\views.py", line 28, in action_active
if not self.handle_view_exception(ex):
File "c:\page\flask_admin\contrib\sqla\view.py", line 1060, in handle_view_exception
return super(ModelView, self).handle_view_exception(exc)
File "C:\page\app\views.py", line 16, in action_active
query = Page.query.filter(Page.active_ind.in_(ids))
AttributeError: type object 'Page' has no attribute 'query'
Since I was using a declarative model, this was the fix. This goes into the models.py file
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
engine = create_engine('databaselinkgoeshere', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
I have a question about flask python.
I tried learning how to build a web using flask, and there is some error. In this case I am using mongoengine as database and JWT(Json Web Token) and the alert error is like this: "TypeError: Expecting a string- or bytes-formatted key"
192.168.100.26 - - [22/Nov/2016 22:50:08] "POST /auth HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "/home/def/.local/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/def/pr/flask/flask_deeper/test/routes/auth.py", line 26, in auth
access_token = _jwt.jwt_encode_callback(identity)
File "/usr/local/lib/python2.7/dist-packages/flask_jwt/__init__.py", line 70, in _default_jwt_encode_handler
return jwt.encode(payload, secret, algorithm=algorithm, headers=headers)
File "/usr/local/lib/python2.7/dist-packages/jwt/api_jwt.py", line 56, in encode
json_payload, key, algorithm, headers, json_encoder
File "/usr/local/lib/python2.7/dist-packages/jwt/api_jws.py", line 98, in encode
key = alg_obj.prepare_key(key)
File "/usr/local/lib/python2.7/dist-packages/jwt/algorithms.py", line 116, in prepare_key
raise TypeError('Expecting a string- or bytes-formatted key.')
TypeError: Expecting a string- or bytes-formatted key.
I thought the error was at this.
models/user.py
#staticmethod
def jwt_handler(token):
if not User.objects(token=token):
raise JWTError("Bad bad bad bad")
secret = str(current_app.config["JWT_SECRET_KEY"])
algorithm = str(current_app.config["JWT_ALGORITHM"])
options = {
'verify_' + claim: True
for claim in verify_claims
}
options.update({
'require_' + claim: True
for claim in required_claims
})
decode = jwt.decode(token, secret, options=options, algorithms=[algorithm])
return decode
#staticmethod
def authenticate(username, password):
user = User.objects(username=username)
if len(user) == 0:
return None
user = user[0]
user["id"] = str(user["id"])
if crypt.verify(password, user.password):
return user
return user
routes/user.py
def auth():
username = request.form.get("username")
password = request.form.get("password")
if not username:
raise BadRequest("Userna doesn't exists")
user = user_ctrl.read(username)
identity = _jwt.authentication_callback(username, password)
if identity:
access_token = _jwt.jwt_encode_callback(identity)
identity.update(push__token=access.decode("utf8"))
return _jwt.auth_response_callback(access_token, identity)
else:
raise JWTError("Bad bad bad very bad")
config.py
import os
from test.models import db
class Config(object):
db_name = os.getenv('MONGODB_NAME', 'third')
db_host = os.getenv('MONGODB_HOST', '127.0.0.1')
db_port = os.getenv('MONGODB_PORT', '5000')
JWT_SECRET_KEY = 'test123'
JWT_ALGORITHM = 'SH256'
JWT_AUTH_ENDPOINT = 'jwt'
JWT_AUTH_USERNAME_KEY = 'username'
JWT_AUTH_PASSWORD_KEY = 'password'
http.py
import logging.config
import jwt
from flask_jwt import JWT
from flask import Flask
from test import routes
from test.models import db, User
_jwt = JWT(authentication_handler=User.authenticate, identity_handler=User.identity)
_jwt.jwt_decode_callback=User.jwt_handler
def create_app(config):
app = Flask(__name__.split(',')[0])
app.register_blueprint(routes.user.bp)
app.register_blueprint(routes.auth.bp)
db.init_app(app)
_jwt.init_app(app)
return app
You have defined the configuration is config.py but have not added the configuration object to your flask app. Therefore, keys such as JWT_SECRET_KEY are not in your app config.
Flask-JWT's default_handler expects those values (Copied in case source changes)
def _default_jwt_decode_handler(token):
secret = current_app.config['JWT_SECRET_KEY']
algorithm = current_app.config['JWT_ALGORITHM']
leeway = current_app.config['JWT_LEEWAY']
In your case as that is not set, it returns None and trips the algorithms.py (which expects a string key).
Therefore, during your app initialization in http.py, you must add a call to app.config.from_object. Maybe something like this
def create_app(config):
app = Flask(__name__.split(',')[0])
# Edit the following to point it to your Config class
app.config.from_object(config.Config)
app.register_blueprint(routes.user.bp)
app.register_blueprint(routes.auth.bp)
db.init_app(app)
_jwt.init_app(app)
return app
On a side note, the name of JWT_ALGORITHM should be HS256 rather than SH256 (Although it doesn't matter as HS256 is the default and will be chosen since SH256 is not a valid algorithm)