Why I can't import class declared in __init__.py? - python

I'm trying to clean up my flask app and I decided to use a boilerplate structure. I have the auth_bp blueprint, it's defined in auth.py , I have the following folder structure;
-app_root
-application
-__init__.py
- auth.py
- other files like template and static
- config.py (for configuration)
- server.py (to run the app through flask_script )
In __init__.py I have two classes: app and mail and I need to use them in my auth.py file.
But when I write :
from application import app, mail
I get an ImportError: cannot import name app
Here's the code in __init__.py:
from flask import Flask
from flask_mail import Mail
import config
from auth import auth_bp
app = Flask(__name__)
app.config.from_object("config.Config")
mail = Mail(app)
app.register_blueprint(auth_bp)
#app.route("/")
def home():
return "homepage"
Edit : Solved: I had to import auth after creating the app and mail object.

Related

Python: unable to import classes from higher directory

I am learning flask. I have a directory structure that looks something like this.
project
- controllers
-- auth.py
-- main.py
- db
-- setup.py
- models
-- models.py
- templates
-- base.html
-- index.html
-- login.html
-- signup.html
-- 404.html
-__init__.py
The file init.py looks like this
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'] = '9OLWxND4o83j4K4iuopO'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:#localhost/mission_to_mars'
db.init_app(app)
# blueprint for auth routes in our app
from .controllers.auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .controllers.main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
I'm trying to import the db variable and create_app() function in controllers/auth.py, controllers/main.py, models/models.py, db/setup.py
I have tried the below syntaxes
from .. import db, create_app
which gives the error:
ImportError: attempted relative import with no known parent package
I have also tried
from project import db, create_app
which gives the error
ModuleNotFoundError: No module named 'project'
I want to know how I can import classes from different directories so that I can use them further in the project.
Thanks in advance

Getting 404 not found on Flask app deployed on PythonAnywhere

I've rummaged through maybe 50 different answers to this and still I haven't manage to fix it... I'm pretty new to flask and python.
I have an app which was running great locally but I've struggled with deploying on python anywhere. Initially I had a few import modules issues, now it runs but doesn't return any html template, despite not seeing any other issue. The main issue I had was that it couldn't find the "routes" app from wsgi, and I sort of fixed adding the app = Flask(name) line on routes.py (the short blueprint object is not callable).
routes.py:
from flask import Blueprint, render_template, request, redirect, send_file
import pyqrcode
from pyqrcode import QRCode
import subprocess
from extensions import db
from models import Link
app = Flask(__name__)
short = Blueprint('short', __name__, url_prefix='/')
#short.route('/index')
def index():
return render_template('index.html')
init.py
from flask import Flask
from extensions import db
from routes import short
def create_app(config_file='settings.py'):
app = Flask(__name__)
app.config.from_pyfile(config_file)
db.init_app(app)
app.register_blueprint(short)
return app
wsgi.py
import sys
# add your project directory to the sys.path
project_home = u'/home/b297py/mysite'
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 routes import app as application
For the purpose of testing, I've placed all the html templates both in the root directory and in the specific /template directory but it just didn't fix the issue.
In wsgi.py you are not calling create_app so you are never registering the blueprint. You should replace :
from routes import app as application
by something like :
from package_name import create_app
application = create_app()
(Example: https://www.pythonanywhere.com/forums/topic/12889/#id_post_50171)
Also as you mentioned, the fix adding app = Flask(__name__) to routes.pyallows you to bypass create_app (so you should remove it if you want to stick to the create_app approach).

Flask passing global variable

I'm trying to passing the flask app context with some global variable to the nested api context.
run.py <= Start the flask application via app.run()
app/
__init__.py
api/
__init__.py
controllers.py
app/__init__.py
from flask import Flask
from app.api.controllers import api
app = Flask(__name__)
app.register_blueprint(api, url_prefix='/api')
main_dict = {"a":"info1", "b":"info2}
app/api/controllers.py
from flask import Blueprint, jsonify
from app import app, main_dict
api = Blueprint('api', __name__)
#api.route('/')
def test():
return jsonify({"status":"OK"})
It throws the following error message:
ImportError: cannot import name 'app'
Thanks!
You've created a circular dependency.
app wants to import app.api.controllers, but that wants to import from app. What you should do to fix it, is to create a new module containing main_dict and import that in both app and app.api.controllers:
# app/__init__.py
from .main_dict import main_dict
from .api.controllers import api
# app/main_dict.py
main_dict = {'a': 'A'}
# app/api/__init__.py
# app/api/controllers.py
from flask import current_app as app
from ..main_dict import main_dict
if you need access to the app outside of app/__init__.py, the recommended way to get at it is to use from flask import current_app

Import statement flow

My app layout
my_app
__init__.py
my_app
__init__.py
startup
__init__.py
create_app.py
create_users.py
common_settings.py
core
__init__.py
models.py
views.py
errors
__init__.py
errors.py
Inner __init__.py
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__) # The WSGI compliant web application object
db = SQLAlchemy(app) # Setup Flask-SQLAlchemy
manager = Manager(app) # Setup Flask-Script
from my_app.startup.create_app import create_app
create_app()
create_app.py
def create_app(extra_config_settings={}):
# Load all blueprints with their manager commands, models and views
from my_app import core
return app
core/__init__.py
# from . import views
views.py
from my_app import app, db
from flask import Flask, request
#app.errorhandler(Error)
def handle_invalid_usage(error):
response = jsonify(data=error.to_dict())
response.status_code = error.status_code
return response
I based this code on a tutorial I found. Everything works fine as long as I leave the __init__.py in the core folder empty.
When I don't, I get a NameError: name Error is not defined in my views.py. Error comes from errors.py.
I have three questions:
1) Why does this happen only when I leave the import statement in core/__init__.py.
2)
create_app.py
app.config.from_envvar('ENV_SETTINGS_FILE')
# Other app.config commands here
from my_app import core
return app
What happens when from my_app import core runs?
3) Finally when I return app, is this to ensure that Inner __init__.py file contains the updated app object?
Any explanations would be greatly appreciated!
Trying to build and configure an app with dynamic imports is really bad news and confusing for the reasons you are discovering. A much better and understandable pattern would be a more typical factory:
def create_app():
app = Flask(__name__)
configure_app(app, config)
register_db(app)
add_views(app)
add_manager(app)
return app
if __name__ == '__main__':
app = create_app()
app.run()
But since you're asking, your problem is here:
from my_app import app, db
from flask import Flask, request
#app.errorhandler(Error) # Error is not imported
def handle_invalid_usage(error):
response = jsonify(data=error.to_dict())
response.status_code = error.status_code
return response
The error occurs because views.py is imported, the code compiler comes across Error and cannot find a reference to it.
For your second question: from my_app import core causes core.__init.__ to run, which (presumably) adds the views onto the app object.

Flask-Restful 404 when api is started in __init__.py

I am using Twilio's flask.ext.restful extension with the following setup:
Top level folder is app
Inside of which is: ___init___.py:
from flask import Flask
from flask.ext import restful
# Basic app configuration
app = Flask(__name__)
api = restful.Api(app)
and inside this app module a file called api.py
from flask.ext.restful import Resource
from app import api
class HelloWorld(restful.Resource):
def get(self):
return {'hello': 'world'}
api.add_resource(HelloWorld, '/hello')
This setup just gives me 404s when accessing /hello
However, if I move the api.py to the __init__.py model then everything works.
Why is this the case?
I think the app gets ran before api.py gets executed and it hangs on Flask. How are you executing this?
class HelloWorld(restful.Resource)
should be
class HelloWorld(Resource)
however
Try transferring from app import api to your __init__.py
from flask import Flask
from flask.ext import restful
# Basic app configuration
app = Flask(__name__)
api = restful.Api(app)
from app import api
Also, you should rename one of the app to avoid confusion.

Categories

Resources