Flask Pluggable Views Error: "Not Implemented Error" - python

I am learning how to use Pluggable Views in Flask, since it seems that everyone uses them always for their advantages. I have the following file which returns an "Not Implemented Error". I am assuming that is because I am not implementing the dispatch_request. However, according to Flask's documentation, when using MethodView: "...if you implement a method called get() it means you will response to ’GET’ requests and the dispatch_request() implementation will automatically forward your request to that." Meaning, I do not require dispatch_request.
from flask import Flask, render_template, request, redirect, url_for, flash
from flask.views import View, MethodView
import os
SECRET_KEY = 'some_secret_key'
DEBUG = TRUE
app = Flask(__name__)
app.config.from_object(__name__)
class Main(View):
def dispatch_request(self):
return "Hello World!"
class Template(View):
def get(self):
return render_template('index.html')
def post(self):
result = eval(request.form['expression'])
flash(result)
return self.get()
app.add_url_rule('/', view_func=Main.as_view('main'))
app.add_url_rule('/template', view_func=Template.as_view('template'), methods=['GET', 'POST'])
if __name__ == "__main__":
app.run()

Oops.. silly Python beginner's mistake by me.
I was subclassing flask.views.View instead of flask.views.MethodView. flask.views.View requires dispatch_request, and does not automatically forward HTTP requests to dispatch_request as MethdoView does, hence the error.

Related

Flask API Calling a Method from Itself

My question is, can an endpoint in a Flask API call a method from another endpoint, that is a member of itself? Is there a proper way of doing this?
Yes, you can indeed call another endpoint by using redirect with url_for
If this is something you are trying to achieve.
from flask import Flask, redirect, url_for
app = Flask(__name__)
#app.route('/')
def hello_world():
return "Hello world"
#app.route('/home')
def hello_again():
return redirect(url_for('.hello_world'))
if __name__=="__main__":
app.run(debug=True)
The request to /home will redirect you to /.

Flask app doen't register jwt.user_lookup_loader, Flask-JWT-Extended

I have a Flask app with blueprints. It worked just fine, but than I decided to use flask_jwt_extended to handle tokens. It is said in docs that I can decorate method with jwt.user_lookup_loader to have current_user working. But for some reason calling current_user ends up with an error:
You must provide a `#jwt.user_lookup_loader` callback to use this method
But it is there, in the same blueprint. There is also a method, decorated with #jwt.user_identity_loader and it works perfectly well.
Here is a simplified version of my code:
from . import rpc, jwt
from flask_jwt_extended import current_user, jwt_required
bp = Blueprint('login_bp', __name__)
#jwt.user_identity_loader
def _user_identity_lookup(user):
return user.id
#jwt.user_lookup_loader
def _user_lookup_callback(_jwt_header, jwt_data):
identity = jwt_data["sub"]
user = rpc.cache_service.get_user(identity)
if user is None:
return None
return UserSchema().load(user)
#jwt_required()
#bp.route("/logout", methods=['POST'])
def logout():
rpc.cache_service.forget_user(current_user.id)
return {"status": "OK"}
jwt here is JWTManager, initialized with my app:
jwt = JWTManager()
def create_app():
app = Flask(__name__, instance_relative_config=False)
app.config.from_mapping(JWT_SECRET_KEY=os.environ["JWT_SECRET_KEY"])
...
jwt.init_app(app)
...
with app.app_context():
from . import login_bp
app.register_blueprint(login_bp.bp)
This code is basicly from the documentation examples:
https://flask-jwt-extended.readthedocs.io/en/stable/automatic_user_loading/
and I can't see what the problem might be (
Link to the repo:
https://github.com/GreenBlackSky/COIN/blob/master/api_app/app/login_bp.py
Your decorators are in the wrong order. #bp.route() needs to come before #jwt_required(), otherwise it tries to evaluate the logout method when a request comes in before it decodes the JWT in the request.

Key Error in Flask Sessions

So I have been using sessions to pass data from one decorator to another. But now every time I make a new session variable, I get a KeyError from page to page. Meaning, I had a session error from my third to fourth page; but I had the same issue adding a new session variable from my second to third page even though I have four other session variables that give me no error.
My code is similar to the one #laila posted below:
from flask import Flask, render_template
from flask import request, session, url_for,abort,redirect
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
#app.route('/'):
def first():
session['this_one']='hello'
render('template.html')
#app.route('/second')
def second():
it=session['this_one']
render('other_page.html')
if __name__ == '__main__':
app.run(debug=True)
it seems like the code has some syntax error.Please try the code below, it should be ok:
from flask import Flask, render_template
from flask import request, session, url_for, abort, redirect
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
#app.route('/')
def first():
session['this_one'] = 'hello'
return render_template('template.html')
#app.route('/second')
def second():
it = session.get('this_one', 'not found')
return render_template('other_page.html')
if __name__ == '__main__':
app.run(debug=True)

Flask: get current blueprint webroot

I am building a Flask app with a blueprint mounted on two different endpoint (one is a legacy alias to the other).
In my blueprint class:
ldp = Blueprint('ldp', __name__)
#ldp.route('/<path:uuid>', methods=['GET'])
#ldp.route('/', defaults={'uuid': None}, methods=['GET'],
strict_slashes=False)
def get_resource(uuid):
# Route code...
In my main server code:
app = Flask(__name__)
app.config.update(config['flask'])
app.register_blueprint(ldp, url_prefix='/new_ep')
# Legacy endpoint. #TODO Deprecate.
app.register_blueprint(ldp, url_prefix='/old_ep')
How can I get the actual URL of the request up to the /old_ep or /new_ep part in the route method, e.g. http://localhost:5000/new_ep?
So far I have used
request.host_url + request.path.split('/')[1]
but it looks quite inelegant and possibly error-prone. I would like to use the information from the blueprint setup if possible.
Thanks for your help.
EDIT: I could get to the Blueprint instance from within the request with
current_app.blueprints[request.blueprint]
and I was hoping that the url_prefix attribute that I set when registering the blueprint was there, but it is None instead. As I read from the documentation for the supposedly related iter_blueprints() method, apparently these blueprints are listed without regard of how many times and with which parameters they were registered. Too bad.
Here is a full working example to get the idea based off issue 612
from flask import Flask, Blueprint, url_for, request, g
bp = Blueprint('whatever', __name__)
#bp.url_defaults
def bp_url_defaults(endpoint, values):
url_prefix = getattr(g, 'url_prefix', None)
if url_prefix is not None:
values.setdefault('url_prefix', url_prefix)
#bp.url_value_preprocessor
def bp_url_value_preprocessor(endpoint, values):
g.url_prefix = values.pop('url_prefix')
#bp.route('/something')
def index():
return 'host prefix is %s%s' % (request.host_url, g.url_prefix)
app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/new_ep', url_defaults={'url_prefix': 'new_ep'})
app.register_blueprint(bp, url_prefix='/old_ep', url_defaults={'url_prefix': 'old_ep'})

Flask blueprints proper usage

I have a question regarding blueprints. I have an app which is structured like this
app
/run.py
/APP
/__init__.py
/VIEWS
/__init__.py
/general.py
/crud.py
this is the code http://pastebin.com/bsHsTGAP
run.py
from overwatch import app
app.run()
__init__.py
from flask import Flask, session, g, render_template, request, redirect, url_for, Response
import websiteconfig as config
from flaskext.principal import Identity, Principal, RoleNeed, UserNeed, \
Permission, identity_changed, identity_loaded
app = Flask(__name__)
app.debug = config.DEBUG
app.secret_key = config.SECRET_KEY
principals = Principal(app)
principals._init_app(app)
#app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
#app.errorhandler(403)
def page_not_found(e):
session['redirected_from'] = request.url
return redirect(url_for('crud.login'))
# handle login failed
#app.errorhandler(401)
def page_not_found(e):
return Response('<p>Login failed</p>')
from overwatch.views import general
from overwatch.views import crud
app.register_blueprint(general.mod)
app.register_blueprint(crud.mod)
general.py
from flask import Blueprint, render_template, session, redirect, url_for, \
request, flash, g, Response, jsonify
from flaskext.principal import Identity, Principal, RoleNeed, UserNeed, \
Permission, identity_changed, identity_loaded
from .. import principals
mod = Blueprint('general', __name__)
normal_role = RoleNeed('normal')
normal_permission = Permission(normal_role)
#mod.route('/')
#normal_permission.require(http_exception=403)
def index():
return "YOU'RE IN"
crud.py
from flask import Blueprint, render_template, session, redirect, url_for, \
request, flash, g, Response, jsonify, abort, Response
from mongokit import Connection, Document
from db import user_exists, email_exists, return_attribute, check_credentials
from forms import RegistrationForm, LoginForm
from .. import app
from flaskext.principal import Identity, Principal, RoleNeed, UserNeed, \
Permission, identity_changed, identity_loaded
from general import normal_role, normal_permission
mod = Blueprint('crud', __name__)
#mod.route('/login/', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
error = None
if request.method == 'POST' and form.validate():
if check_credentials(form.username.data,form.password.data):
identity = Identity(form.username.data)
identity_changed.send(app, identity=identity)
return redirect(session['redirected_from'])
else:
return abort(401)
return render_template('login.html', form=form, error=error)
#app.route("/logout/")
def logout():
for key in ['identity.name', 'identity.auth_type', 'redirected_from']:
try:
del session[key]
except:
pass
return Response('<p>Logged out</p>')
#identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
identity.provides.add(normal_role)
Thing is, I seem to be importing a lot of stuff into a lot of stuff. Right now it works. if i go to the index paged, which is handled by general.py blueprint and secured with normal_permission it redirects to /login which is handled by crud.py blueprint and if logged in redirects to index. Again, right now it... works but .. it also feels realllllllllly dirty and unclean and .. bleac... so unlike some of the good code I read :)
Any suggestions are welcome please. If this is not the way to tackle it, I'm willing to learn. I dont want to have some code that .. just works.
Thank you for your time reading this and maybe answering it.
ps. if i pasted too much code here let me know and I'll edit it out.
To access the current application from your blueprint's views, you should use the flask.current_app object, it is a proxy to the current application (and it's what's used in flask extensions for example).
Regarding your code, except the unused imports, it's well organised in my opinion, but i can't tell about the principal part, as i've never used it.

Categories

Resources