Sphinx documentation inside a Flask running web application - flask

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

Related

Django dev server not recognizing new files after directory modification

I have a Django project with 2 apps and was writing some functions in a utils.py file in one of the apps. I wanted to break this up into two separate files in their own subdirectory so I created a new directory 'utils' a level below the app directory and placed the two utils1.py and utils2.py files in there.
I had some issues with importing something from the other app so I ended up scrapping this idea and moving everything back into one file in the base directory of the original app, exactly like it was before. Now when I runserver it is not picking up any new files that are created within apps. Not just the ones that I recreated but any new files. Files that were created prior to the change are running just fine.
So, in summary new utils.py files that I recreated in the app directory are not running when the dev server is started, and when I try to run one of them manually they run like any other python file, but imports from other locations in the project are not being recognized.
No other changes were made and new files were running perfectly fine before the directory changes.
After the changes:
├── app1
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── permissions.py
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── app2
├── __init__.py
├── admin.py
├── apps.py
├── utilities <--- added
├── util1.py
└── util2.py
├── migrations
├── models.py
├── serializers.py
├── tests.py
├── urls.py
└── views.py
After reverting back to previous structure (not working):
├── app1 <--- new files created here aren't running
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── permissions.py
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── app2 <--- new files created here aren't running
├── __init__.py
├── admin.py
├── apps.py
├── util1.py <--- moved back into app directory
├── migrations
├── models.py
├── util2.py <--- moved back into app directory
├── serializers.py
├── tests.py
├── urls.py
└── views.py
I've tried clearing the pycache files, restarting the dev server, restarting terminal, etc. to no avail.
I figured out what was going on. My assumption was that any new python files in an installed app would be automatically run, but something from the file needs to be imported first from somewhere else in the project. Before the changes I had an import in the utils.py file so the dev server was running it, but after the changes there were no imports from elsewhere in the project. Issue is fixed and working now.

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

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!

Blueprint template folder in flask not working as expected

This is my project structure:
├── run.py
└── test_blueprint
├── __init__.py
├── __init__.pyc
├── mainsite
│   ├── controllers
│   │   ├── controllers.py
│   │   ├── controllers.pyc
│   │   ├── __init__.py
│   │   └── __init__.pyc
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── static
│   │   ├── css
│   │   │   ├── bootstrap.min.css
│   │   │   └── signin.css
│   │   └── js
│   └── templates
│   └── mainsite
│   └── homepage.html
├── static
│   ├── css
│   │   ├── bootstrap.min.css
│   │   └── signin.css
│   └── js
├── templates
│   └── mainsite
│   └── index1.html
└── usermanagement
├── controllers
│   ├── controllers.py
│   ├── controllers.pyc
│   ├── __init__.py
│   └── __init__.pyc
├── __init__.py
├── __init__.pyc
├── static
└── templates
Here I have two blueprints, mainsite and usermanagement. I have registered them in file __init__.py under the test_blueprint folder which is the main folder (one below the blueprint_project folder which has run.py).
__init__ file under test_blueprint
from flask import Flask
app = Flask(__name__)
from test_blueprint.mainsite.controllers.controllers import mod
from test_blueprint.usermanagement.controllers.controllers import mod
app.register_blueprint(mainsite.controllers.controllers.mod, url_prefix="/")
app.register_blueprint(usermanagement.controllers.controllers.mod, url_prefix="/usermanagement")
Now post that I have under each blueprint folder I have created __init__.py in which I have defined Blueprints along with template folder. However, it does not take the template from there. It keeps on throwing error 'template not found'. So, I have created template folder under test_blueprint folder. It perfectly picks index.html from templates/mainsite folder.
Also, if I provide /home/user/flaskenv/blueprint_project/... templates folder which is an absolute path for my template under blueprint folder, it works fine.
Not sure if the bug is in Flask. I saw a video on YouTube and expected my flask project to behave the same. Unfortunately it didn't.
This is what my controller.py/views.py file looks like for mainsite:
from flask import Blueprint, render_template, url_for
mod = Blueprint('mainsite', __name__, static_folder='static',template_folder='templates')
#mod.route("/")
def home():
return render_template('mainsite/homepage.html')
Now if I used os.path.abspath to locate the template folder under the blueprint folder, and then passed that path as variable to template_folder, it works fine.
Now my expectation as per flask documentation is that just mentioning template_folder='templates' should automatically locate templates under the blueprint folder or it entirely defeats the purpose.
I solved by renaming the html file by unique name

Create react app + Django deployment Uncaught SyntaxError: Unexpected token <

I've been trying to deploy an app to pythonanywhere but the page is just blank, because main.6f259c1b.js file throws error`
Uncaught SyntaxError: Unexpected token <
`
I've been following the instuctions on this article https://www.fusionbox.com/blog/detail/create-react-app-and-django/624/ and this https://www.techiediaries.com/create-react-app-django/
both articles suggest to create a view with following content
class FrontendAppView(View):
"""
Serves the compiled frontend entry point (only works if you have run `yarn
run build`).
"""
def get(self, request):
try:
with open(os.path.join(settings.REACT_APP_DIR, 'build', 'index.html')) as f:
return HttpResponse(f.read())
except FileNotFoundError:
logging.exception('Production build of app not found')
return HttpResponse(
"""
This URL is only used when you have built the production
version of the app. Visit http://localhost:3000/ instead, or
run `yarn run build` to test the production version.
""",
status=501,
)
and in app website/urls.py
urlpatterns = [
url(r'^', FrontendAppView.as_view())
]
Those instructions don't work for me. It's something that related to pushState routing, react-routing, I don't know. My app works ok in development server in localhost:3000, it only seen in pythonanywhere and local apache server with mod_wsgi.
This is my config of local apache(from Django documentation):
WSGIScriptAlias / /home/user/projects/myproject/myproject/wsgi.py
WSGIPythonHome /home/user/.virtualenvs/myproject
WSGIPythonPath home/user/projects/myproject/
<Directory /home/user/projects/myproject/myproject>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
This is root
DocumentRoot "/srv/http"
Part of my settings
REACT_APP_DIR = os.path.join(BASE_DIR, 'frontend')
STATIC_URL = '/static/'
STATIC_ROOT = 'static'
STATICFILES_DIRS = [
os.path.join(REACT_APP_DIR, 'build', 'static')
]
All software are latest release.
Maybe this comment solves my problem, I just don't understand it. https://github.com/facebookincubator/create-react-app/issues/1812#issuecomment-286511320
This is my localhost screenshot
My project directory structure
├── api_v0
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── __pycache__
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── myproject
│   ├── __init__.py
│   ├── local.py
│   ├── __pycache__
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── frontend
│   ├── build
│   ├── node_modules
│   ├── package.json
│   ├── package-lock.json
│   ├── public
│   ├── README.md
│   └── src
├── manage.py
├── requirements.txt
├── static
│   ├── admin
│   ├── css
│   ├── js
│   ├── media
│   └── rest_framework
└── website
├── admin.py
├── apps.py
├── __init__.py
├── management
├── middleware.py
├── migrations
├── models.py
├── __pycache__
├── tests.py
├── urls.py
└── views.py
Review the styles referenced on the page and make sure that all the CSS files are referenced on the page using a <link> tag and not a <script> tag.
reference
also there are nginx adubting , you can do it for request your site adminstator help

ShimmerCat - Use ShimmerCat as a reverse proxy for a Django app

I have tested ShimmerCat (https://www.shimmercat.com/) and sc-tool (https://pypi.python.org/pypi/sc-tool/) using this (https://www.shimmercat.com/en/info/articles/getting-started/). I am trying to deploy the application locally but a 404 error occurs.
This is the structure of my project:
├── db.sqlite3
├── devlove.yaml
├── manage.py
├── testapp
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── templates
│   │   └── home.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── testproject
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
└── static
│   ├── base.css
And this is my devlove.yaml file:
shimmercat-devlove:
domains:
www.test.com:
root-dir: testproject
consultant: 8080
cache-key: xxxxxxx
I haven't made any changes to settings.py
Do you have any suggestions on how to solve the 404 error? Thank you in advance.
With web-servers, you usually have your static files served by the webserver itself and the dynamic part of the application being proxied by the web server to your application.
So, a starting setup for your project would be:
shimmercat-devlove:
domains:
static.test.com:
root-dir: static
cache-key: xxxxxxx
www.test.com:
port: 8080
Everything indented under "static.test.com" would be served as static resources, therefore you need to modify your settings.py file to identify "static.test.com" as your static domain:
STATIC_URL="https://static.test.com/"
In addition to that, you would need to run your Django application in one of the usual ways, simultaneously with the server. For example, you could start by launching:
$ python manage.py runserver
and then in a new terminal invoke ShimmerCat's from the project's directory:
$ shimmercat devlove