route endpoint conflicts when generating sphinx doc for flask restful api - python

I'm trying to build documentation for a Flask webapp that includes a REST-like API built into it. I'm using sphinx, specifically the httpdomain extension from sphinxcontrib, using the autohttp.flask module to auto-generate my Flask docs, and the autohttp.qrefflask module to auto-generate a quick reference table to go along with it. However, when I try to build my sphinx docs (make html), I'm running into the error of conflicting route endpoints
Exception occurred:
File "/Users/../anaconda2/lib/python2.7/site-packages/flask/app.py", line 1051, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: api.View1:add_config
I only really care about generating documentation for my API and none of the Flask web routes, so I've restricted my sphinx documentation to only build the api blueprints. Here is my sphinx api.rst
.. qrefflask:: myapp.web:create_app(debug=True)
:undoc-static:
:endpoints:
:blueprints: api
:order: path
.. autoflask:: myapp.web:create_app(debug=True)
:undoc-static:
:endpoints:
:blueprints: api
:order: path
My Flask app and Blueprint layout is as follows:
myapp/
api/
__init__.py (api blueprint defined here)
view1.py
view2.py
view3.py
web/
__init__.py (main Flask app created here via create_app)
I'm wondering if it's a problem with how I'm registering the blueprint, and that sphinx somehow is registering it twice, but I don't understand it.
My api.__init__.py basically has my Blueprint definition and a few custom error handlers:
from flask import Blueprint, jsonify
theapi = Blueprint("api", __name__, url_prefix='/myapp/api')
#theapi.errorhandler(500)
def internal_server_error(err):
messages = {'error': 'internal_server_error',
'message': err.description,
'traceback': get_traceback(asstring=True)}
return jsonify({
'api_error': messages,
}), 500
while my main Flask app creation, web.__init__.py just imports this and registers everything:
def create_app(debug=False, local=False):
from myapp.api import theapi as api
from myapp.api.view1 import View1
...
app = Flask(__name__, static_url_path='/myapp/static')
...
View1.register(api)
app.register_blueprint(api)
return app
If I move the api blueprint definition and error_handlers into the main app creation, everything works fine. But then that breaks the modularity of it. I'd like to keep my api stuff inside the api module. Also, if remove either the main autoflask or qrefflask generation, and only use one, everything works fine. But I'd really like to have the quick reference guide. The code itself runs fine, but the damn documentation is failing to build. Does anyone have any suggestions?

Related

Access flask app context in worker to access database

I am trying to access db.session in a Flask-RQ job to update my database.
The thing is that I am not able to do it as my app context is not known by the worker which is executing jobs.
I am also using Flask Blueprints to structure my application so I am not able to use app context with from app import app.
Below my application structure:
--> app
--> __init__.py
--> jobs.py
--> routes
--> routes.py
config.py
I created a Blueprint for jobs.py but when I trigger my job in routes.py file I have an error when trying to do query with db.session (note that db is imported with from app import db and session with from flask import session).
RuntimeError: No application found. Either work inside a view function or push an application context.
The job is pretty simple:
#rq.job
def try_rq():
print("Starting task")
db.session.query(...)
print("Task completed")
I do not know how to make my worker knowing the application context and so be able to use db.session to update my database.
Note that without database update the job is working fine.

How to extending config in view

I have an external package that installs (pip install) in venv with my pyramid project. And I want extending config in the view. The client.include.my_pack have this function adding router:
def includeme(config):
config.add_route('my_url_view', url)
This package should be used in multiple projects and I want to connect it in only one place in the project.
I try connect it:
from pyramid.view import view_config
from pyramid.config import Configurator
config = Configurator()
config.include('client.include.my_pack')
config.scan()
#view_config(route_name='my_url_view', request_method='POST', renderer='json')
def home(request):
pack = request.validated['expected']
return pack
But this code raise exceptions:
pyramid.exceptions.ConfigurationExecutionError: <class 'pyramid.exceptions.ConfigurationError'>: No route named expected found for view registration.
How can I add route in the display instead of __ init __.py project file?
The exception is "No route named expected found for view registration". Your examples talk about a route named "my_url_view", not "expected". I suspect you have another view referencing a route that is not defined? I don't see anything wrong with your pasted code.

Example of RESTful API in Flask Python

Can someone show me examples of making a RESTful API which uses database information in Flask? I have no idea how to implement POST, PUT and DELETE and I always get the 405 error where I can't use the method in url.
Have you add request method in your routing? you can following reference from: flask-restful
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class TodoSimple(Resource):
def get(self):
# do get something
def put(self):
# do put something
def delete(self):
# do delete something
def post(self):
# do post something
api.add_resource(TodoSimple, '/api/todo')
if __name__ == '__main__':
app.run(debug=True)
in flask-restful the HTTP actions (GET, PUT, POST, DELETE) have their corresponding method in the resource class, so is just a matter of defining those method in the resource (with the corresponding parameter defined in the routing)
I've also built a lightweight framework for building restful apis that makes it super easy to build apis. You can take a look at the code to have an idea of how an API can be built, configured and run, and of course, build on top of it
here's the code: https://github.com/sebastiandev/peach

Flask-Restful ignores blueprint's url_prefix

I want to use Flask blueprints to organize my Flask-Restful resources into separate url prefixes. Regardless of what url prefix I set (during either blueprint creation or registration), everything gets mapped to the raw route paths. How do I correctly use Restful with blueprints?
app = Flask(__name__)
api = Api(app)
api.add_resource(Building, '/<int:id>', endpoint='building')
api.add_resource(Jack, '/<int:id>', endpoint='jack')
building_api = Blueprint('building_api', __name__)
jack_api = Blueprint('jack_api', __name__)
app.register_blueprint(building_api, url_prefix='/buildings')
app.register_blueprint(jack_api, url_prefix='/jacks')
All documentation I can find says that these should now be available at /buildings/<int:id> and /jacks/<int:id>, but both of those urls 404 and instead I can access the building one at /<int:id>. Hard coding the path in add_resource fixes it, but defeats the point of url_prefix.
You need to pass the blueprint to the Api instance, not the app.
building_bp = Blueprint('buildings', __name__)
building_api = Api(building_bp)
building_api.add_resource(Building, '/<int:id>')
app.register_blueprint(building_bp, url_prefix='/buildings')
This is zhe best way to do with blueprint:
from flask import Flask, Blueprint
from flask_restful import Api, Resource, url_for
app = Flask(__name__)
api_bp = Blueprint('api', __name__)
api = Api(api_bp)
class TodoItem(Resource):
def get(self, id):
return {'task': 'Say "Hello, World!"'}
api.add_resource(TodoItem, '/todos/<int:id>')
app.register_blueprint(api_bp)
you should send Blueprint'instance to Api
I do not know why but I struggled using the Blueprint as mentioned in the answers.
But here's a quick solution I found while going through the doc link. Making use of the prefix parameter in Api() does the job.
app = Flask(__name__)
api = Api(app, prefix='/buildings')
Now, all your routes will be prefixed with /buildings. Just make sure you use url_for('link') in places where you might have simply used a /link.
One more strange thing I noticed is that atleast for me, it did not work until I renamed my routes to the same name as their class names. For example, Class Home(Resource) should have a route to /home. Using /homeepage or any other route for Home Class causes an error. Not sure if it is only me.

Flask per-blueprint error pages

I have a flask application that looks somewhat like this:
app.py
blueprints/
www.py
shop.py
app.py imports blueprint objects from each of the files in the blueprints directory and registers them with the Flask object in app.py with an appropriate subdomain (also imported from the file). Each blueprint registers error handlers, however these are only invoked when a view manually calls abort(), not by general errors (i.e. calling a non existent URL on the subdomain managed by shop.py invokes the error handler on app.py instead.)
Is there any way to force flask to pass errors to the blueprint that is handling the subdomain in which that error is occurring?
Flask's documentation says that this is not possible for 404s and 500s. If you need this functionality you might be able to use a wildcard route in your blueprint to handle 404s:
#a_blueprint.route("<path:invalid_path>")
def missing_resource(invalid_path):
return "There isn't anything at " + invalid_path, 404
You can use current_app and put it in the blueprints. Something like:
shop.py
from flask import current_app
#current_app.errorhandler(404)
def page_not_found(e):
return redirect(url_for('shop.index'))

Categories