I'm getting an 404 errors when trying to setup routes for a Flask + Restplus app.
#api.route('/')
class asd(Resource):
def get(self):
return "asd"
Always return 404 error/ If I add #api.route('/'something) I can access "/something" URL without an error.
What do I miss? Or it's not possible when using Flask + Restplus?
I've tried adding '/' route tu the api an dto the app with same results.
app and api defines in separate class for server
class Server(object):
def __init__(self):
self.app = Flask(__name__)
self.api = Api(self.app,
version='0.1',
title='API',
description='A simple API',
doc = environment_config["swagger-url"]
)
def run(self):
self.app.run(
debug = environment_config["debug"],
port = environment_config["port"]
)
server = Server()
Related
i am trying to generate Flask route using a basic DI i.e mapping methods as route handlers, i am a total beginner at Flask so mind my basic skills
class myClass():
def __init__(self):
self.dbConnObj = DbToolsMySql('someconnection', 'slave')
self.dbConnObj.connect()
self.blueprint = Blueprint('myClass', __name__)
self.blueprint.add_url_rule('/my_method', view_func=self.my_method)
def my_method(self, event):
retun "hello"
and then in my handler file
from flask import Flask
from flask_restful import Api, Resource
from src.app.services.myClassimport myClass
app = Flask(__name__)
app.register_blueprint(myClass.blueprint)
if __name__ == "main":
app.run()
Quite simple ehh???? but not working... i am getting following message
Not Found The requested URL was not found on the server. If you
entered the URL manually please check your spelling and try again.
typically you add routes to the Flask app with decorators like so:
app = Flask(__name__)
#app.route('/some-endpoint')
def some_endpoint_handler():
# do something
pass
Or you can add without a decorator like so:
def some_endpoint_handler():
# do something
pass
app = Flask(__name__)
app.route('/some-endpoint', methods=['GET'])(some_endpoint_handler)
So in your scenario, you can pass the app.route call to your myClass object and set the route like this:
class myClass():
def __init__(self, router):
self.dbConnObj = DbToolsMySql('someconnection', 'slave')
self.dbConnObj.connect()
self.blueprint = Blueprint('myClass', __name__)
#self.blueprint.add_url_rule('/my_method', view_func=self.my_method)
router('/my_method', ['GET'])(self.my_method)
def my_method(self, event):
retun "hello"
myObj = myClass( app.route )
or, invert the dependency:
app = Flask(__name__)
#app.route(myClass.blueprint.some_endpoint_string)
def some_endpoint_handler():
myClass.blueprint.call_some_endpoint_handler()
pass
if __name__ == "main":
app.run()
the docs suggest using factory function.
def create_app():
app = Flask(__name__)
return app()
so I don't have access to my app when I'm writing my code,
for this porpuse there is an object called " current_app " in flask module,
so I did this and I got " out of application context error "
#current_app.before_request
def before_req():
whatever...
how can I define before request functions when I'm using a factory function?!
You can define your before_request function inside create_app function:
def create_app():
app = Flask(__name__)
#app.before_request
def before_request(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
return app
If you use Flask Blueprints, you define before_request function for your blueprint like this:
from Flask import Blueprint
my_blueprint = Blueprint('my_blueprint', __name__)
#my_blueprint.before_request
def before_request(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
I've a flask web app in which I authenticate to the "core" DB as admin.
MONGO_URI = "mongodb://myUserAdmin:abc123#localhost:27017/test?authSource=admin"
mongo = PyMongo(app)
# ... and I am able to interact with the DB
flash(mongo.db.user.find_one())
now, I want to create sub-DBs for each user of the app and let him modify only its specific DB (or table). How can I configure flask to manage that? I tried to look in web but found no solutions.
Thanks in advance for any help!
You can do something like this
Create Authentication middleware
class UserAuthenticationMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
'''
Authenticate the user here
'''
self.app.user = {'_id': ObjectId('ddddddddssssssssssss')} # authenticate the user and get it from db
return self.app(environ, start_response)
Then create a Database middleware to get a db for the user
class DbMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
if hasattr(self.app, 'user'):
# create a database by user id or you can use any unique field here
self.app.db = self.app.db_client[str(self.app.user._id)]
else:
self.app.db = self.app.db_client['default_db']
return self.app(environ, start_response)
Then in create app instance
from flask import Flask
if __name__ == '__main__':
app = Flask(__name__)
app.db_client = MongoClient()
app = DbMiddleware(UserAuthenticationMiddleware(app))
app.run()
I am attempting to convert a collection of Flask apps to a single app with several Blueprints.
In one of my apps, I have a task that runs periodically in the background, not related to a request. It looks something like this:
import apscheduler.schedulers.background
import flask
app = flask.Flask(__name__)
app.config['DATABASE']
scheduler = apscheduler.schedulers.background.BackgroundScheduler()
scheduler.start()
def db():
_db = flask.g.get('_db')
if _db is None:
_db = get_db_connection_somehow(app.config['DATABASE'])
flask.g._db = _db
return _db
#scheduler.scheduled_job('interval', hours=1)
def do_a_thing():
with app.app_context():
db().do_a_thing()
When I convert this app to a Blueprint, I lose access to the app object and I can't figure out how to create an application context when I need one. This is what I tried:
import apscheduler.schedulers.background
import flask
bp = flask.Blueprint('my_blueprint', __name__)
scheduler = apscheduler.schedulers.background.BackgroundScheduler()
scheduler.start()
def db():
_db = flask.g.get('_db')
if _db is None:
_db = get_db_connection_somehow(flask.current_app.config['DATABASE'])
flask.g._db = _db
return _db
#bp.record
def record(state):
with state.app.app_context():
flask.g._app = state.app
#scheduler.scheduled_job('interval', hours=1)
def do_a_thing():
with flask.g._app.app_context():
db().do_a_thing()
The error I get is:
RuntimeError: Working outside of application context.
So, how can I get the application context in a blueprint but outside a request?
I solved this problem with the following changes. First, I set up a scheduler object on my Flask app:
app = flask.Flask(__name__)
app.scheduler = apscheduler.schedulers.background.BackgroundScheduler()
app.scheduler.start()
Next, I changed the function that runs my background task to accept the app as an argument, so I could read the database connection information from app.config:
def do_a_thing(app: flask.Flask):
db = get_db_connection_somehow(app.config['DATABASE'])
db.do_a_thing()
Finally, I set up the scheduled job in Blueprint.record():
#bp.record
def record(state):
state.app.scheduler.add_job(do_a_thing, trigger='interval', args=[state.app], hours=1)
Suppose I need to do before_request for each flask servers
How can I share the following snippet to each servers without COPY-PASTE
#app.before_request
def before_request(*args, **kwargs):
params = get_params()
if params.has_key('start_dt') and params.has_key('end_dt'):
g.mongo_query = Mongo.get_date_range_query(params)
else:
g.mongo_query = {}
You could use application factory for this. If you initialize your flask applications like so:
from flask import Flask
import yourdb
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
yourdb.init_app(app)
#add_extensions
#add_blueprints/views
# ... some other configuration ...
#app.before_request
def before_request(*args, **kwargs):
#Your code
return app
From manage/run, you would then
from somewhere import create_app
app = create_app(<your_config>)