Reputation: 546
I am trying to deploy a Flask web to a Debian server. The files' structure is the following:
run.py
config.py
requirements.txt
/app
constants.py
errors.py
forms.py
__init__.py
models.py
routes.py
/static
/css
/vendor
bulma.css
/js
/vendor
fontawesome.js
/templates
index.html
login.html
404.html
In order to deploy it on the server, I create a virtualenv and install the requirements.txt. Then, I start the web running the Python file run.py
. When then I try to load the index page or the login page, it is unable to find any of the routing paths (although it works fine locally). Also, it is unable to locate the CSS
and JS
files. Instead of that, it fires the error handler on errors.py
, raising an HTML error 404. The content of the files where I think the problem might be located is listed bellow:
Content of run.py
from app import app, db, socketio
from flask_assets import Environment, Bundle
from flask import Flask
if __name__ == '__main__':
assets = Environment(app)
assets.register('mainCss', \
'css/vendor/bulma.css', filters='cssmin')
assets.register('mainJs', \
'js/own.js', 'js/vendor/fontawesome.js', filters='jsmin')
socketio.run(app, debug=False, port=80, host= '0.0.0.0')
Content of config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
ADMINS = ['[email protected]']
Content of /app/__init__.py
import logging
from logging.handlers import SMTPHandler, RotatingFileHandler
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from config import Config
from flask_socketio import SocketIO
from threading import Lock
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
thread = None
thread_lock = Lock()
socketio = SocketIO(app)
from app import routes, models, errors
Content of /app/routes.py
from flask import render_template, flash, redirect, url_for, request
from app import app, db
from app.forms import LoginForm
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
#Validate login
return redirect(url_for('index'))
return render_template('login.html', title='Login', form=form)
@app.route('/index', methods=['GET', 'POST'])
def index():
return render_template('index.html', title='Index')
Therefore, my question is: why does this work locally but it fails to find the paths of the static files when deployed to a Debian server and how can I solve this issue?
EDIT: I've just realised that the problem is that on the server, my page is hosted on an extra directory, such as www.myweb.com/directory
, while when running local my webpage is on localhost:5000/
, therefore the page is unable to locate the CSS and JS files on the server due to the extra directory
. Now I am trying to figure out how to couple with this extra level on the url. I believe this could be done with something like this, but for the time being I am not able to find the correct implementation for this issue.
Upvotes: 3
Views: 1321
Reputation: 4190
You can use DispatcherMiddleware
The first parameter of the DispatcherMiddleware
constructor is the fallback application, in case no paths are found, if we pass the original wsgi_app
your application will still be available in root path /
.
The second parameter is a dictionary of prefixes: applications. {'/directory': app}
will make requests of /directory
be forwarded to your app
Here's how you can glue everything together
from app import app, db, socketio
from flask_assets import Environment, Bundle
from flask import Flask
from werkzeug.middleware.dispatcher import DispatcherMiddleware
if __name__ == '__main__':
assets = Environment(app)
assets.register('mainCss', \
'css/vendor/bulma.css', filters='cssmin')
assets.register('mainJs', \
'js/own.js', 'js/vendor/fontawesome.js', filters='jsmin')
app.wsgi_app = DispatcherMiddleware(
app.wsgi_app, # If path is not found use the original wsgi_app
{'/directory': app} # If prefix is /directory pass it to app
)
socketio.run(app, debug=False, port=80, host= '0.0.0.0')
Upvotes: 2