Getting error - KeyError: when using sessions in flask - python

I am storing something in session, and when I am trying to access it in another .py file, it doesnt recognize it, but it is stored because i print it after entering it in session and it prints.
my server py where i insert into session
from flask import render_template, redirect, request, flash, session
from flask_socketio import SocketIO, send
from flask_app.controllers import users_controller
from flask_app.controllers import scores_controller
import json
import ast
socketio = SocketIO(app, cors_allowed_origins="*")
players_choices = []
#socketio.on('message')
def handle_message(message):
print("\n\n\nMESSAGE TYPE ")
print(message)
print("\n\n\nCHOICEEEEEE END")
if message != "User connected!":
send(message, broadcast=True)
extracted_string = message['json']
print("\n\n\nIM AM HERE***********")
print(extracted_string)
choices = ast.literal_eval(extracted_string)
print("\n\n\nPRINTING JSONED DIC")
print(choices['user_id'])
print(choices['choice'])
players_choices.append(choices)
print("\n\n\nPLAYERS CHOICES")
print(players_choices)
if len(players_choices)>=2:
session['main_user_choice'] = players_choices[0]
session['opponent_user_choice'] = players_choices[1]
print("\n\n\nSESSION VALUES")
print(session['main_user_choice'])
print(session['opponent_user_choice'])
print("SESSION VALUES\n\n\n")
destination = '/result/player'
socketio.emit('redirect', destination)
print("\n\n\nAFTER EMIT\n\n\n")
# return redirect('/result')
if __name__ == "__main__":
socketio.run(app, host='localhost', port=5001)
It fails here: which is in another user controller file in the same app
#app.route('/result/player')
def result_player():
if 'user_id' not in session:
return redirect('/')
data = {
'id' : session['user_id']
}
print(session['main_user_choice'])
print(session['opponent_user_choice'])
if 'main_user_choice' not in session:
return redirect('/gameplay/player')
if 'opponent_user_choice' not in session:
return redirect('/gameplay/player')
But here is also the console prints and error
MESSAGE TYPE
User connected!
CHOICEEEEEE END
MESSAGE TYPE
127.0.0.1 - - [02/Feb/2023 11:09:46] "GET /socket.io/?EIO=4&transport=websocket&sid=azlEIxJRmda1mG87AAAE HTTP/1.1" 200 -
{'json': "{'user_id': 'Sam', 'choice' : '1'}"}
CHOICEEEEEE END
IM AM HERE***********
{'user_id': 'Sam', 'choice' : '1'}
PRINTING JSONED DIC
Sam
1
PLAYERS CHOICES
[{'user_id': 'Ashot Gharibyan', 'choice': '1'}, {'user_id': 'Sam', 'choice': '1'}]
SESSION VALUES
{'user_id': 'Ashot Gharibyan', 'choice': '1'}
{'user_id': 'Sam', 'choice': '1'}
SESSION VALUES
AFTER EMIT
127.0.0.1 - - [02/Feb/2023 11:09:46] "GET /socket.io/?EIO=4&transport=websocket&sid=EXVg2E0k5b2kaPfVAAAC HTTP/1.1" 200 -
Running Query:
SELECT *
FROM users
WHERE id = 3;
127.0.0.1 - - [02/Feb/2023 11:09:46] "GET /waiting_for_opponent HTTP/1.1" 200 -
[2023-02-02 11:09:46,248] ERROR in app: Exception on /result/player [GET]
Traceback (most recent call last):
File "/Users/coding-workspace/.local/share/virtualenvs/rps-GYIrbTZz/lib/python3.11/site-packages/flask/app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/coding-workspace/.local/share/virtualenvs/rps-GYIrbTZz/lib/python3.11/site-packages/flask/app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/coding-workspace/.local/share/virtualenvs/rps-GYIrbTZz/lib/python3.11/site-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/coding-workspace/.local/share/virtualenvs/rps-GYIrbTZz/lib/python3.11/site-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/coding-workspace/Desktop/CodingDojo/Python/FinalProject/rps/flask_app/controllers/users_controller.py", line 267, in result_player
print(session['main_user_choice'])
~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "/Users/coding-workspace/.local/share/virtualenvs/rps-GYIrbTZz/lib/python3.11/site-packages/flask/sessions.py", line 80, in __getitem__
return super().__getitem__(key)
^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'main_user_choice'
So it says that the 'main_user_choice' is not in session, but it is when I print it in the server.py file, but it is not in the user_controller.py file
UPDATE: I figured that it is not saved in the same session, that is why its not recognizing.
How can I implement something that would be transffered to all the sessions in the program? I am building a rock paper, scissors game, 2 players connect to the server, they put in their choice, and i want to put them together so i can compare. Any tips how can i do that with socketio?

Related

Dash Web-app doesn't work. Error: POST /_dash-update-component HTTP/1.1" 500 -

I am just starting to learn a Python web-app library "Dash", that's why I could possibly ask sily questions.
Basically my following code will create a dashboard by using a python library "Dash". If everything works fine, I could select from a dropdown one out of 3 stock tickers (Apple, Tesla, Coca Cola). After selecting it, the stock price dated back to 01.01.2016 until now will be shown.
My code is:
from pandas_datareader import data
import plotly.graph_objects as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from datetime import datetime as dt
app = dash.Dash(__name__)
app.layout = html.Div([
html.H3('Stock Tickers'),
dcc.Dropdown(
id='my-dropdown',
options=[
{'label': 'Coke', 'value': 'COKE'},
{'label': 'Tesla', 'value': 'TSLA'},
{'label': 'Apple', 'value': 'AAPL'}
],
value='COKE'
),
dcc.Graph(id='my-graph', figure={})
])
#app.callback(
[Output(component_id='my-graph', component_property='figure')],
[Input(component_id='my-dropdown', component_property='value')])
def update_graph(dropdown_properties):
selected_value = dropdown_properties['value']
df = data.DataReader(selected_value, 'yahoo', dt(2016, 1, 1), dt.now())
print(df[:5])
figure = go.Figure(data=[go.Scatter(x=df.index, y=df.Close,
name=selected_value)])
return {
'figure': figure}
if __name__ == '__main__':
app.run_server()
I got following error messages:
Dash is running on http://127.0.0.1:8050/
* Serving Flask app "Stock_Ticker" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
127.0.0.1 - - [27/Mar/2021 13:20:10] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [27/Mar/2021 13:20:12] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [27/Mar/2021 13:20:12] "GET /_dash-dependencies HTTP/1.1" 200 -
[2021-03-27 13:20:12,391] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\dash\dash.py", line 1078, in dispatch
response.set_data(func(*args, outputs_list=outputs_list))
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\dash\dash.py", line 1009, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
File "C:\Users\Gunardilin\Desktop\Value Investing Dashboard\Dash\Stock_Ticker.py", line 39, in update_graph
selected_value = dropdown_properties['value']
TypeError: string indices must be integers
127.0.0.1 - - [27/Mar/2021 13:20:12] "POST /_dash-update-component HTTP/1.1" 500 -
[2021-03-27 13:20:18,959] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\dash\dash.py", line 1078, in dispatch
response.set_data(func(*args, outputs_list=outputs_list))
File "C:\Users\Gunardilin\anaconda3\lib\site-packages\dash\dash.py", line 1009, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
File "C:\Users\Gunardilin\Desktop\Value Investing Dashboard\Dash\Stock_Ticker.py", line 39, in update_graph
selected_value = dropdown_properties['value']
TypeError: string indices must be integers
127.0.0.1 - - [27/Mar/2021 13:20:18] "POST /_dash-update-component HTTP/1.1" 500 -
From the link (http:...), I could only see a blank graph:
I would be very thankful, if someone can pinpoint what my mistake is.
The value from your dropdown comes through as one of the following:
'COKE'
'TSLA'
'AAPL'
but you're treating it as if it came through like this:
{'label': 'Coke', 'value': 'COKE'},
{'label': 'Tesla', 'value': 'TSLA'},
{'label': 'Apple', 'value': 'AAPL'}
Basically, you can just delete this line:
selected_value = dropdown_properties['value']
and your code should work.

Flask-socketio AttributeError: 'Request' object has no attribute 'sid'

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.

Can't pass variables to html through flask

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())

TypeError: Expecting a string- or bytes-formatted key when using Flask-JWT

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)

Flask test_client can't handle HTTP 204 No data

I have delete endpoint, returning HTTP 204
#blueprint.route('/foo', methods=['DELETE'])
def delete_tag(id):
# ....
return '', 204
and I want to test it
def test_delete_tag(self):
resp = self.client.delete(url_for('tags.delete_tag', id=1))
self.assertEqual(resp.status_code, 204)
but I got exception
Traceback (most recent call last):
File "tests/tags_test.py", line 31, in test_delete_tag
resp = self.client.delete(url_for('tags.delete_tag', id=1)})
File ".virtualenvs/...site-packages/werkzeug/test.py", line 799, in delete
return self.open(*args, **kw)
File ".virtualenvs/...site-packages/flask/testing.py", line 108, in open
follow_redirects=follow_redirects)
File ".virtualenvs/...site-packages/werkzeug/test.py", line 742, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File ".virtualenvs/...site-packages/werkzeug/test.py", line 659, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File ".virtualenvs/.../site-packages/werkzeug/test.py", line 885, in run_wsgi_app
buffer.append(next(app_iter))
StopIteration
with response status 200 it works all fine. Is there way how to fix the test?
The mining of 204 is "no content" at all, it's assume that you're not going to add any body in that response.
small flask app:
from flask import Flask, request
app = Flask(__name__)
#app.route('/foo', methods=['DELETE'])
def delete_tag():
print("i got", request.form['id'])
return '', 204
#app.route('/foo2/<id>', methods=['DELETE'])
def delete_tag2(id):
print("i got.. .", id)
return '', 204
if __name__ == '__main__':
app.run(debug=True)
and in ipython qtconsole; i did this:
In [3]: from app import app
In [4]: from flask import url_for
In [5]: c = app.test_client()
In [6]: with app.test_request_context():
...: rv = c.delete(url_for('delete_tag2', id=55))
...: print(rv.status_code)
...:
i got.. . 55
204
In [7]: rv = c.delete("/foo", data={"id": 555})
i got 555
In [8]: rv.status_code
Out[8]: 204

Categories