Relative imports in pythonanywhere do not work in flask project - python

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()

Related

Python flask with multi modules application OperationalError: (sqlite3.OperationalError) no such table

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

Why I can't move import at top?

I am learning Flask. I found example with follow code
__init__.py:
from flask import Flask
app = Flask(__name__)
from app import views
view.py:
from app import app
#app.route('/')
def index():
return "hello world"
and run.py (on top level):
from app import app
app.run()
I can't understand why I can't move from app import views to the top. If I do so I am getting error:
> run.py
Traceback (most recent call last):
File "F:\app1\run.py", line 1, in <module>
from app import app
File "F:\app1\app\__init__.py", line 2, in <module>
from app import views
File "F:\app1\app\views.py", line 1, in <module>
from app import app
ImportError: cannot import name 'app'
Python is interpreted language. When it comes to one line it try to execute it. And that is why you cannot import views before defining app.
Working version of __init__.py
app = Flask(__name__)
from app import views # it will "execute: views.py"
# views.py - indenting for better understanding
from app import app # App is defined here and it can be imported
Not working version of __init__.py
from app import vies # it will execute vies.py"
# vies.py - indenting for better understanding
from app import app # Exception - app doesn't exist here
app = Flask(__name__)
You need to be really careful with python imports.
In run.py file line
from app import app
means "from package app (folder with __init__.py file, F:\app1\app in your case, import object app", and in __init__.py file line
app = Flask(__name__)
creates an application object. Main confusion caused by your application name - app - which coincides with application object name.
If you move line
from app import views
above
app = Flask(__name__)
from app import app in view.py will raise ImportError, because object app from app package not defined yet.

Trying to run the sql-alchemy tutorial steps. Can't import db from console (ImportError: cannot import name 'db')

Trying to run the tutorial here: http://flask-sqlalchemy.pocoo.org/2.1/quickstart/ using my app
I have looked at the circular imports problem but I don't think that's it. I'm an absolute beginner to python and flask (and sqlalchemy). My app currently runs, but the database part doesn't
This is the current setup:
mysite
|- __init__.py
|- flask_app.py
|- models.py
|- views.py
init.py
from flask import Flask
app = Flask(__name__)
flask_app.py
from flask import Flask, request, url_for
import random
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:// -- database uri --'
... app continues here
models.py
from app import app
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
class Foo(db.Model):
... model continues here
views.py
from app import app,models
... views continue here, still not using anything from models
when I run from mysite import db in the python console I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'db'
Declare your db object in __init__.py. The stuff that is declared in __init__.py defines what can be imported under mysite/.
See: What is __init__.py for?
Also consider moving to the application factory pattern.
For example in __init__.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['DEBUG'] = True
... more application config ...
db.init_app(app)
return app
Then in flask_app.py:
from mysite import create_app, db
app = create_app()
if __name__ == '__main__':
app.run()
I point this out because you instantiate the app object twice in the code you've shown. Which is definitely wrong.

Structure Flask project so I can import my app in other files

I built this app a few months ago on the flask server and it was working perfectly. I have uploaded all files into the right directories but I keep getting an Unhandled Exception saying there is No module named app.
Here is my structure:
/static/
(all static files)
/templates/
(all html files)
myapp.py
In myapp.py:
from app import app
from flask import render_template, redirect, request, url_for
#index - Home page containing images for the trailer, discussion thread and cast
#app.route('/')
#app.route('/index')
def index():
page_info = {
'title':'Star Wars - Forums',
}
img1 = 'pan.jpg'
img2 = 'trailerlink.jpg'
img3 = 'trailerdiscussion.jpg'
img4 = 'episode7cast.jpg'
return render_template('index.html', info=page_info, imgone=img1, imgtwo=img2,imgthree=img3, imgfour=img4)
In my wsgi.py file:
import sys
# add your project directory to the sys.path
project_home = u'/home/myusername'
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 myapp import app as application
And finally some of the errors in my error log:
File "/bin/user_wsgi_wrapper.py", line 122, in __call__ app_iterator = self.app(environ, start_response)
File "/bin/user_wsgi_wrapper.py", line 136, in import_error_application
raise e
ImportError: No module named app
It's probably just something small, it usually is, but I can't seem to find it. Can anyone help?
It looks like you're trying to refer to your project as a package. You need to actually create a package called "app" if you want to do from app import app.
myproject/
app/
__init__.py # contains `app` object
views.py # was called myapp.py, does `from app import app`
static/
templates/
wsgi.py # does `from app import app as application`
In this case the Flask app should be defined in __init__.py so that importing it from the myapp modules works. Realistically, this naming scheme makes no sense, it looks like myapp.py should really be called views.py.

deployment of Flask application to OpenShift

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/

Categories