I'm trying to deploy a flask app on a shared server (hostgator) using CGI but I'm getting a URL not found error when I use the base URL (mysite.com/) and all others. I've set up a virtual environment in the public_html/ folder with python 2.7.8 and Flask 0.12.4 (newer versions of flask not supported on python 2.7.8 because they use SSLContext).
I've determined that the .htaccess file and cgi-bin/main.cgi file are configured correctly by writing a small flask hello_world app in the public_html/ folder that works and runs the website. And I've tried checking the error logs on cpanel which are empty and couldn't find any other useful logs in the file system. I've also set all the permissions to 755 which is what hostgator recommended to no avail.
My file system is this:
public_html/
flask_hello_world.py
some .html files for testing
cgi-bin/
main.cgi
server/
app.py
__init__.py
views.py
models.py (sqlalchemy models)
static/
some .html files
My .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /home4/MYSITE/public_html/cgi-bin/main.cgi/$1 [L]
Addhandler cgi-script .py .cgi
main.cgi:
#!/home4/MYSITE/public_html/venv/bin/python
import sys
sys.path.insert(0, '/home4/MYSITE/public_html/venv/lib/python2.7/site-packages/')
sys.path.insert(1, '/home4/MYSITE/public_html/server/')
from wsgiref.handlers import CGIHandler
from app import app
class ProxyFix(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
environ['SERVER_NAME'] = ""
environ['SERVER_PORT'] = "80"
environ['REQUEST_METHOD'] = "GET"
environ['SCRIPT_NAME'] = ""
environ['QUERY_STRING'] = ""
environ['SERVER_PROTOCOL'] = "HTTP/1.1"
return self.app(environ, start_response)
if __name__ == '__main__':
app.wsgi_app = ProxyFix(app.wsgi_app)
CGIHandler().run(app)
And when I changed main.cgi to run flask_hello_world.py it ran just fine. Here's that code:
import flask
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return flask.send_from_directory('/home4/MYSITE/public_html/','index.html')
#app.route('/hello')
def hello():
return flask.send_from_directory('/home4/MYSITE/public_html/','hello.html')
Moving my main project .py files into the public_html folder did not solve the problem. Heres app.py and init.py from the actual project:
app.py:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
from flask import Flask
##other imports including sqlalchemy
app = Flask(__name__)
app.config["CACHE_TYPE"] = "null"
# sqlalchemy setup
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'database.db')
##some other configurations
db = SQLAlchemy(app)
migrate = Migrate(app, db)
# flask login setup
login_manager = LoginManager()
login_manager.login_view = "login_view"
login_manager.init_app(app)
init.py:
from app import app, db, login_manager
import models
import views
My views.py has no import errors when I just run it using 'python views.py' and the route for '/' is identical to the hello world app. So I think there is a problem with app.py, init.py, or the fact that my routes aren't in the app.py file.
The problem might have been that the views are not imported in app.py or init.py, so are unknown to the application. Thus the CGI script threw the URL not found.
Related
I've been trying to deploy my Flask app to Heroku for over a day, watching/reading several tutorials, and digging through all the stackoverflow questions i could find and still haven't found a solution for my issue. When i deploy my app, I get the error "gunicorn.errors.AppImportError: Failed to find attribute 'app' in 'app'." I've changed my Procfile many times to get heroku to run my app but i always get the same error.
This is how my app is structured:
enter image description here
My Procfile includes this statement:
web: gunicorn app:app --preload
I am thinking my issues could be how im creating my app, but could not find a solution. My main app file looks like this:
from venv import create
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os.path import join, dirname, realpath
from flask_login import LoginManager
db = SQLAlchemy()
def create_app():
app = Flask(__name__, static_folder='static')
app.debug = True
app.config['SECRET_KEY'] = 'abcde12568901fghij'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
app.config['SQLALCHEMY_DATABASE_URI'] = '[removed for privacy]'
app.config['UPLOAD_DIRECTORY'] = join(dirname(realpath(__file__)), 'uploads/')
app.config['MAX_CONTENT_LENGTH'] = 16*1024*1024 #16mb
app.config['ALLOWED_EXTENSIONS'] = ['.jpg','.jpeg','.png','.gif','.mp4']
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from models import User
#login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
from auth import auth
app.register_blueprint(auth)
from views import main
app.register_blueprint(main)
return app
if __name__ == '__main__':
db.create_all(app=create_app())
Screenshot of full logs:
enter image description here
Any help would be greatly appreciated, thanks all!
app:app tells Gunicorn to look for a variable called app in your app.py file (strictly speaking, in your app module), but you don't have a variable with that name.
Instead, you have a function create_app() that returns your app object. Gunicorn allows you to use that directly:
The variable name can also be a function call. In that case the name will be imported from the module, then called to get the application object. This is commonly referred to as the "application factory" pattern.
Update your Procfile accordingly:
web: gunicorn 'app:create_app()' --preload
Do you have another file in your root directory that is creating the app or is the code above the file that you run to run the app? This will normally just be a Python file with the name of your project, and this will have something like app = create_app().
Then your Procfile needs to look for the app in that file.
For example if that file was called mainApp.py you would then use
web: gunicorn mainApp:app --preload
I am trying to learn from a very helpful tutorial
https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login
on how to use flask_login.
My question: The complete tutorial works fine for me on my local PC, however I run into problems when trying to get this running on pythonanywhere.
The error seems ot be related to relative imports. In the best case, I want to come up with some code which runs both locally on my machine and on pythonanywhere.
For a minimal example, the project structure is as follows:
└── flask_auth_app
└── project
├── __init__.py
├── auth.py
├── main.py
with the files
__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret-key-goes-here'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db.init_app(app)
# blueprint for auth routes in our app
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
auth.py
from flask import Blueprint
from . import db
auth = Blueprint('auth', __name__)
#auth.route('/login')
def login():
return 'Login'
#auth.route('/signup')
def signup():
return 'Signup'
#auth.route('/logout')
def logout():
return 'Logout'
main.py
from flask import Blueprint
from . import db
main = Blueprint('main', __name__)
#main.route('/')
def index():
return 'Index'
#main.route('/profile')
def profile():
return 'Profile'
To execute this on my local PC, I create an environment variable
set FLASK_APP=project
and run flask from the flask_auth_app directory
flask run
and everything runs fine.
I have now transferred the files to pythonanywhere and use the following configuration there:
source code: /home/grammaster/flask_auth_app
working directory: /home/grammaster/flask_auth_app
WSGI configuration file
# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project
import sys
# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app/project'
if project_home not in sys.path:
sys.path = [project_home] + sys.path
# import flask app but need to call it "application" for WSGI to work
from project import app as application # noqa
The resulting error message is
2021-08-13 05:58:26,704: Error running WSGI application
2021-08-13 05:58:26,706: ImportError: cannot import name 'app' from 'project' (/home/grammaster/flask_auth_app/./project/__init__.py)
2021-08-13 05:58:26,706: File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 05:58:26,707: from project import app as application # noqa
If I change the settings to
source code: /home/grammaster/flask_auth_app/project
working directory: /home/grammaster/flask_auth_app/project
and use
from main import app as application # noqa
the resulting error is
2021-08-13 06:10:53,086: Error running WSGI application
2021-08-13 06:10:53,089: ImportError: attempted relative import with no known parent package
2021-08-13 06:10:53,089: File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 06:10:53,089: from main import app as application # noqa
2021-08-13 06:10:53,089:
2021-08-13 06:10:53,089: File "/home/grammaster/flask_auth_app/project/main.py", line 2, in <module>
2021-08-13 06:10:53,089: from . import db
I am sure that the problem is rather trivial, but I seem to lack some basic understanding of relative imports on pythonanywhere and a flask server in general.
I have finally found the solution of getting the above example working with relative imports and on pythonanywhere. The problem was originating from wrong paths in the WSGI configuration file.
For the example and the paths above, the correct WSGI configuration file is
# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project
import sys
# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app'
if project_home not in sys.path:
sys.path = [project_home] + sys.path
# import flask app but need to call it "application" for WSGI to work
from project import create_app
application = create_app()
I'm trying to run my flask app with "python app.py" instead of "flask run" command.
My goal is to launch the app on cpanel server and just about every tutorial requires the applications to be called using the "python" method.
Here is my folder structure:
project
webapp
init.py
templates
static
auth.py
main.py
app.py <-------------- I want this to be called with python instead of flask run command outside the folder
Here is my init_.py file:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = '9OLWxND4o83j4iuopO'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import User
#login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
# blueprint for auth routes in our app
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
And app.py is:
from webapp import app
I'm a newbie in flask, any help is appreciated
Insert the call to create_app at the end of init.py:
if __name__ == '__main__':
create_app().run(host='0.0.0.0', port=5000, debug=True)
The if statement avoid calling the app many times. It can only be called directly. Flask default host is 127.0.0.1 (localhost). Use 0.0.0.0 at production for better traffic monitoring. Default port is also 5000, so it's up to you to include. For better readability, you should explicit it.
Then call it
python webapp/init.py
I have been learning python recently and practiced a couple of tutorials and its been going fine, till I have divided my application to sub modules to make it easier to maintain using blueprints, after doing so the application crashed and throw the following error: OperationalError: (sqlite3.OperationalError) no such table, here is how im dividing my application:
-instance
-flask.cfg
-app
- static // Folder for css
- templates // Folder for common html files
-__init__.py // to init the app
-module1
-__init__.py // to register module blueprint
-subModule1
-subModule1 Group1
-templates
-htmls files
-__init__.py file //to register group1 blueprint
-Group1Form
-Group1Model
-Group1View
-subModule1 Group2
-templates
-htmls files
-__init__.py file //to register group2 blueprint
-Group2Form
-Group2Model
-Group2View
-subModule2
....
-main.py
The application run fine when I use flask run but I have an issue when I use db.session.add() method with the exception that the table was not found. I have tried many solutions to this issue but no luck. here is some links for the same issue:
OperationalError: (sqlite3.OperationalError) no such table: user
https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/
Python sqlite3.OperationalError: no such table:
'No application found. Either work inside a view function or push an application context.'
Here is the flask.cfg file:
import os
BASEDIR = os.path.abspath(os.path.dirname(__file__))
SECRET_KEY = os.urandom(32)
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.abspath('app.db')
And here is how I am initializing the app in the main __init__.py file:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config_filename=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile(config_filename)
initialize_extensions(app)
register_blueprints(app)
def create_app(config_filename=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile(config_filename)
initialize_extensions(app)
register_blueprints(app)
return app
def initialize_extensions(app):
db.init_app(app)
with app.app_context():
db.create_all()
def register_blueprints(app):
from app.module1.config.university import university_blueprint
app.register_blueprint(university_blueprint)
from app.module1.config.department import department_blueprint
app.register_blueprint(department_blueprint)
from app.module1.authors.author import author_blueprint
app.register_blueprint(author_blueprint)
from app.module1.authors.publications import publications_blueprint
app.register_blueprint(publications_blueprint)
can you move db.init_app() inside app.app_context() function
with app.app_context():
db.init_app()
I figured out the issue, I was suppose to place:
with app.app_context():
db.create_all()
after registering the blueprints
I would like to deploy my application which works fine on my local unix server to OpenShift cloud. I registered there and checkout git repository. But I don't know what to do now.
Application in this repository has following structure:
/libs
/app.py
/setup.py
/wsgi
static/
application
but I don't know where I should copy my project in which files should be modified. My project structure is following
/domain.wsgi
/domain/
app.py
infrastructure.py
models/
static/
templates/
views/
domain.wsgi
import sys, os
current_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(current_dir)
from domain.app import app as application
app.py
from infrastructure import app
import views.index
import views.login
import views.logout
import models.sa
infrastructure.py
from flask import Flask, g
from flask.ext.sqlalchemy import SQLAlchemy
from models.sa import get_user_class, UserQuery
from models.database import db_session
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://.............'
db = SQLAlchemy(app)
## Set SQL Alchemy to automatically tear down
#app.teardown_request
def shutdown_session(exception=None):
db_session.remove()
# Instantiate authentication
User = get_user_class(db.Model)
# config
app.config.update(
DEBUG = True,
SECRET_KEY = 'xxxxxxxxx'
)
Thanks
You files go under wsgi folder; please see this tutorial on how to deploy flask applications to OpenShift: http://www.paasmag.com/2013/01/08/beginners-guide-to-writing-flask-apps-on-openshift/