Flask-Swagger-UI does not recognize path to swagger.json - flask

I'm building an API, using Flask and flask-restful and flask-swagger-ui. I have now modified the project structure and now I can no longer access the project's swagger.json file.
Based on the package documentation flask-swagger-ui, you would only need to change the parameter API_URL to the correct path. But even when entering relative path or full path, I can no longer access the file.
My Code:
from flask import Flask, jsonify
from flask_migrate import Migrate
from flask_restful import Api
from flask_swagger_ui import get_swaggerui_blueprint
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
api = Api(app, prefix="/api/v1")
'''swagger specific'''
SWAGGER_URL = '/api/v1/docs'
# API_URL = 'templates/swagger.json'
API_URL = 'app/templates/docs/swagger.json'
SWAGGERUI_BLUEPRINT = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "My Rest App"
}
)
app.register_blueprint(SWAGGERUI_BLUEPRINT, url_prefix=SWAGGER_URL)
db.init_app(app)
Migrate(app, db)
return app
My Tree Structure:
├── API
│   ├── app
│   │   ├── __init__.py
│   │   ├── models
│   │   │   ├── __init__.py
│   │   │   ├── db.py
│   │   │   └── db2.py
│   │   ├── routes
│   │   │   ├── __init__.py
│   │   │   ├── resources.py
│   │   └── templates
│   │   └── docs
│   │   └── swagger.json
│   ├── app.db
│   ├── config.py
│   ├── main.py
│   ├── migrations
│   ├── requeriments
│   └── tests
└── README.md
I need help, to understand the problem of the path to the file and thus correct the problem.

I believe that its a restriction on flask's end, but it seems like you must place static files in a folder explicitly named static/ at the root of your flask app.
Try changing
API_URL = 'app/templates/docs/swagger.json'
to
API_URL = '/static/swagger.json'
Then create a static/ folder in API/app/, and move your json into it. Like so: API/app/static/swagger.json
If that doesn't work, make sure you have the static/ folder in the correct directory, try print(app.root_path) after defining your flask app variable in order to see what flask considered the root path to be.

We can't provide any custom file path for swagger.json.
But there is one catch which we can do if you require.
I was facing the same issue where I need to provide different prefix for swagger URL and swagger.json.
If we just want to serve swagger.json file from a different prefix instead of '/static/swagger.json':
Then make changes as below:
APP = Flask(__name__, static_url_path = '/my-prefix/static')
API_URL = '/my-prefix/static/swagger.json'

For me "root_path" solved the problem,
Lets say I have the following path:
"C:\script\mycode\src\swagger.json"
def resource_path(relative_path):
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
new_path = resource_path("swagger.json")
new_path = new_path.replace("swagger.json", "")
app = Flask(__name__, root_path=new_path, static_folder="")
print("app.root_path ===================>>",app.root_path)
#prints: "C:\script\mycode\src\"
app.register_blueprint(get_swaggerui_blueprint(
'/api/swagger',
"\\swagger.json", #put starting slash even the app.root_path ends with
#slash. and check in "app.root_path" if additional path
#need to be added with "\\swagger.json"
config=apiConfig),
url_prefix=apiPrefixV1+'swagger',
name='v1')
Note: For me resource path is used for pyinstaller build. For local test also works fine!

Related

How to import the template into a subdirectory of the templates folder in Flask?

Currently I have an API project, based on flask-restful, with documentation page created with OpenAPI (Swagger). I'm trying to create a login page, based on my structure jinja2 can not find the path to the template.
In the login script, I tried to pass the full path to the .html file, in the render_template() function, but did not find the file. Just like adding the parameter template_folder = path/to/file in app=Flask(__name__) and I did not succeed.
My Structure:
├── app
│   ├── __init__.py
│   ├── auth
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── login.py
│   ├── common
│   │   ├── __init__.py
│   │   ├── jwt.py
│   │   ├── request.py
│   │   └── utils.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── core.py
│   │   └── db_app_2.py
│   ├── routes
│   │   ├── __init__.py
│   │   ├── resources.py
│   └── templates
│   ├── docs
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   └── pages
│   ├── base.html
│   ├── login.html
│   └── signup.html
├── app.db
├── config.py
├── main.py
├── migrations
├── requeriments
└── tests
login.py
# -*- coding: utf-8 -*-
from flask import Blueprint, render_template, redirect, url_for
from app.models.core import db
auth = Blueprint('auth', __name__)
#auth.route('/login')
def login():
return render_template('login.html')
#auth.route('/signup')
def signup():
return render_template('signup.html')
__init__.py(main project)
from flask import Blueprint, Flask
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_restful import Api
from config import config
from .models.core import db
from .routes.resources import TwoThings
def create_app(config_name):
app = Flask(__name__, template_folder="/templates/pages")
app.config.from_object(config[config_name])
'''Fixed path for routes the api'''
path_prefix = '/api/v1'
api_bp = Blueprint(path_prefix, __name__)
api = Api(api_bp)
from app.auth.login import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix=path_prefix)
api.add_resource(Reset, f'{path_prefix}/two_things')
app.register_blueprint(api_bp)
db.init_app(app)
Migrate(app, db)
return app
I need to create a login page, to be accessible by the browser and once logged in redirect to the documentation endpoint.
Try:
return render_template('pages/login.html')
In your login.py.

Combining React and Flask Routing

I'd like to handle all routing on the client side with two exceptions:
The server should handle any route that begins with /api and serve the files from /dist.
Here's my folder structure:
./
├── Client
│   ├── dist
│   │   └── bundle.js
│   │   └── bundle.css
│   ├── index.html
│   ├── node_modules
│   ├── package.json
│   ├── src
│   │   ├── __tests__
│   │   ├── components
│   │   └── index.tsx
│   ├── tsconfig.json
│   ├── tslint.json
│   ├── webpack.config.js
│   └── yarn.lock
├── README.md
├── app.py
└── requirements.txt
app.py
from flask import Flask, jsonify, render_template
app = Flask(__name__, template_folder="Client")
#app.route('/api/random')
def random_name():
response = {
'randomName': choice(["Ben", "Joe", "Robert", "Amy"])
}
return jsonify(response)
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def index(path):
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
How can I serve bundle.js from index.html?
I've tried using url_for in the index.html but it doesn't work - I get a 404.

Sphinx fails when generating documentation for Django project

I'm trying to automatically generate documentation for my Django project using Sphinx with the autodoc and napoleon extensions.
Using sphinx-quickstart I've created the following structure:
MyDjangoProject
├── __init__.py
├── config
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── docs
│   ├── Makefile
│   ├── build
│   └── source
│   ├── _static
│   ├── _templates
│   ├── conf.py
│   └── index.rst
├── myfirstapp
│   ├── __init__.py
│   ├── models.py
│   └── views.py
├── mysecondapp
│   ├── __init__.py
│   ├── models.py
│   └── views.py
...
I've customized docs/source/conf.py to reflect my project structure.
import os
import sys
proj_folder = os.path.realpath(
os.path.join(os.path.dirname(__file__), '../..'))
sys.path.append(proj_folder)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
import django
django.setup()
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.napoleon', 'sphinx.ext.viewcode']
# The rest of the default configuration...
Then I go to the root of my project and run sphinx-apidoc -f -o docs/source .. This adds a .rst file for each module to docs/source.
Finally I go to MyDjangoProject and run make html. This fails with an error for each module saying
Traceback (most recent call last):
File "/Users/Oskar/git/MyDjangoProject/venv/lib/python2.7/site-packages/sphinx/ext/autodoc.py", line 551, in import_object
__import__(self.modname)
ImportError: No module named MyDjangoProject.myfirstapp
What am I doing wrong?
Since you have added MyDjangoProject to the python path, you should import myfirstapp as myfirstapp instead of MyDjangoProject.myfirstapp.

Flask Blueprint; No module found named

I'm trying to get Flask Blueprints running in Docker, but having issues with registering Blueprints correct.
I have the following structure:
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── sites-enabled
│   └── flask_project
└── web
├── Dockerfile
├── __init__.py
├── app.py
├── modules
│   ├── __init__.py
│   └── page
│   ├── __init__.py
│   ├── forms.py
│   ├── models.py
│   ├── views.py
├── requirements.txt
├── static
│   ├── css
│   │   ├── bootstrap.min.css
│   │   └── main.css
│   ├── img
│   └── js
│   └── bootstrap.min.js
└── templates
├── _base.html
└── index.html
app.py contains:
from flask import Flask
from web.modules.page import simple_page
app = Flask(__name__)
app.register_blueprint(simple_page)
if __name__ == '__main__':
print app.url_map
app.run(debug=True)
views.py contains:
from flask import Blueprint
simple_page = Blueprint('simple_page', __name__,
template_folder='templates')
#simple_page.route('/')
def index():
return "Hello world"
__init__.py under page:
from web.modules.page.views import simple_page
The __init__.py files are empty.
The console gives an ImportError: No module named web.modules.page
Thanks for your time.
Look like is structure problem, you can reference from here: https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications
The following is my example, hope it can help for you:
├── app
│   ├── __init__.py
│   ├── main
│   │   ├── __init__.py
│   │   └── views.py
│   ├── models
│   │   └── __init__.py
│   ├── static
│   │   ├── css
│   │   ├── js
│   │   ├── img
│   │   └── file
│   ├── templates
│   │   └── index.html
└── master.py
app/__init__.py
from flask import Flask
from app.main import main
def create_app():
app = Flask(__name__)
app.register_blueprint(main)
return app
app/main/__init__.py
from flask import Blueprint
main = Blueprint('main', __name__)
from app.main import views
master.py
from app import create_app
if __name__ == '__main__':
app = create_app()
app.run(host='0.0.0.0', port=8000, threaded=True)

Sphinx documentation inside a Flask running web application

I've locally built static Sphinx documentations (using make html).
I wish now to integrate the Sphinx files into my webapp that runs with Flask. From the Flask running application, I simply mean to include an hyperlink towards the Sphinx documentation, that will serve as help for the application.
Websupport seems the way to follow, but it's not clear to me how I should bridge the Flask framework to the Sphinx files.
Thanks for any help,
Regards
Other solutions nicely omit the Flask object initialization, which lead me to bang my head against the wall for a while.
Without touching the Sphinx project structure at all, here's the solution that worked for me:
from flask import Flask
app = Flask(__name__, static_url_path='/', static_folder='_build/html/')
#app.route('/')
#app.route('/<path:path>')
def serve_sphinx_docs(path='index.html'):
return app.send_static_file(path)
if __name__ == '__main__':
app.run(debug=True)
And below is the file structure of the project, where <doc> represents the rst files I actually wrote for the documentation, and app.py is the file containing the Flask app code above.
.
├── Makefile
├── _build
│   ├── doctrees
│   │   ├── index.doctree
│   │   ├── <doc>.doctree
│   │   ├── ...
│   │   └── <doc>.doctree
│   └── html
│   ├── _images
│   ├── _modules
│   │   ├── index.html
│   │   └── <package name>
│   │   └── ...
│   ├── _sources
│   │   ├── <doc>.rst.txt
│   │   ├── ...
│   │   └── <doc>.rst.txt
│   ├── _static
│   │   ├── ajax-loader.gif
│   │   ├── alabaster.css
│   │   └── ...
│   ├── genindex.html
│   ├── index.html
│   ├── objects.inv
│   ├── py-modindex.html
│   ├── search.html
│   ├── searchindex.js
│   ├── <doc>.html
│   ├── ...
│   └── <doc>.html
├── _static
│   ├── custom.css
│   └── <myimage>.gif
├── _templates
├── app.py
├── conf.py
├── index.rst
├── make.bat
├── <doc>.rst
├── ...
└── <doc>.rst
You could just handle it with your web server, the same way you handle the /static directory in Flask. For example if you used Apache as your production web server, you might add
Alias /documentation /location/of/sphinx/html
<Directory /location/of/sphinx/html>
Order deny,allow
Allow from all
</Directory>
to your Apache site configuration, so then you could just link directly to http://yoursite.com/documentation to access the Sphinx files, avoiding Flask altogether.
You can copy the _build/html folder from your docs to a doc folder in your flask static directory, and serve them with the following rule:
#app.route('/doc/<dir>/<filename>', defaults={'static': True})
def doc(dir='',filename='index.html'):
path = join(dir,filename)
return app.send_static_file(path)
In some cases you do not want to expose your docs to all users so configuring at the Apache or Nginx level is not an option. The following worked for me:
#app.route('/docs', defaults = {'filename': 'index.html'})
#app.route('/docs/<path:filename>')
#login_required
def web_docs(filename):
path = os.path.join('docs/html', filename)
return app.send_static_file(path)
As far as I've seen the Flask.send_static_file method requires that the file resides within the static directory. Sub directories are not supported using this method.
To serve a file from any location use the Flask.send_from_directory method.
Example:
import flask
from flask import send_from_directory
app = Flask(
import_name=__name__
)
#app.route('/docs/', defaults={'filename': 'index.html'})
#app.route('/docs/<path:filename>')
def docs(filename) -> flask.send_from_directory:
docs_dir = os.path.join(os.path.dirname(__file__), 'docs', 'build', 'html')
return send_from_directory(directory=docs_dir, path=filename)
The example assumes docs\build\html\ exists in the same directory as the python file. Change docs_dir as needed.
Additionally, without appending a trailing backslash to the default route, the page did not render properly, therefore I changed the default route to /docs/.
Set the BUILDDIR path in sphinx Makefile
BUILDDIR = app/static/docs
add flask routes
#app.get('/docs/')
#app.get('/docs/<path:filename>')
def get_docs(filename='index.html'):
path = os.path.join('docs/html', filename)
return app.send_static_file(path)
Build the sphinx documentation.
$ make html
You can browse to http://127.0.0.1:5000/docs for sphinx documentation page. All the sphinx docs static files will be served under this route. You can also add Flask Authentication to the route if needed.
Test Versions:
Flask: 2.0.2
Sphinx: 4.3.1