Object is not imported properly in a Flask structure - python

I'm trying to learn Flask from Instant Flask Web Development book following it step-by-step but I get the error presented below.
(It seems to be a problem with circular imports.)
The questions are:
Can someone explain what would be the fix and detail the circular imports?
Directory structure:
├── manage.py
├── requirements.txt
└── sched
├── __init__.py
├── __init__.pyc
├── app.py
├── app.pyc
├── static
└── templates
manager.py:
from flask.ext.script import Manager
from sched import app
manager = Manager(app)
app.config['DEBUG'] = True
if __name__ == '__main__':
manager.run()
app.py:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
__init__.py is ampty.
Command line generated error:
$ python manage.py runserver
Traceback (most recent call last):
File "manage.py", line 8, in <module>
app.config['DEBUG'] = True
AttributeError: 'module' object has no attribute 'config'

When you do
from sched import app
you are importing the app module. The app object is inside the module. The import you want to use is
from sched.app import app

Alternative architecture :
# app.py:
from flask import Flask
app = Flask(__name__)
app.debug = True
from flask.ext.script import Manager
manager = Manager(app)
# __init__.py:
from .sched import app, manager
import sched.views # for your views
import sched.commands # for additional commands
# manager.py:
from sched import manager
if __name__ == '__main__':
manager.run()
#views.py:
from .app import app
#app.route('/')
def hello_world():
return 'Hello World!'

I suggest following an app factory pattern for your app.
manage.py
sched/
__init__.py
in __init__.py you can do the following:
from flask import Flask
def create_app():
app = Flask(__name__)
app.config['DEBUG'] = True
return app
in manage.py
from app import create_app
from flask.ext.script import Manager
app = create_app()
manager = Manager(app)
if __name__ == '__main__':
manager.run()
This tends to be an extensible solution for larger application structures.

Related

Initializing database with flask

I have the following code:
init.py:
"""Initialize app."""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
"""Construct the core application."""
app = Flask(__name__, instance_relative_config=False)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['RECAPTCHA_PUBLIC_KEY'] = '6LcmEeoUAAAAAIbdhgkFBvz676UCRJMjnSx8H6zy'
app.config['RECAPTCHA_PARAMETERS'] = {'size': '100%'}
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)
with app.app_context():
# Import parts of our application
from . import routes
return app
and I try to initialize the db with the following code:
from realProject import db, create_app
db.create_all(app=create_app())
all of the scripts are in realProject folder
but when trying to compile the last code I get this error:
ModuleNotFoundError: No module named 'realProject'
What am I doing wrong?
You need to follow this structure :
|__project_name
|__app.py ----------> The main file from where you run your app
|__app -----> This is the app folder
├── templates
│ └── index.html
└── __init__.py -----------> The __init__.py should be inside the app folder for it to be imported
└── routes.py
And then do this in your main file :
from app import db, create_app
db.create_all(app=create_app())

How to import blueprints with the same name as the file they are in?

Background
I'm trying to set up a blueprint whose name matches the filename it resides in, so that when I reference it in my app.py I know where the blueprint comes from. This should be possible because the example on exploreflask uses the same pattern. Still, I cannot figure out how to make this work with my structure.
File structure
├── app.py
├── frontend
   ├── __init__.py
   └── views
   ├── home.py
   └── __init__.py
Example
frontend/views/home.py
from flask import Blueprint, render_template
home = Blueprint('home', __name__)
home1 = Blueprint('home1', __name__)
frontend/views/__init__.py
from .home import home
from .home import home1
app.py
from flask import Flask
from frontend.views import home
from frontend.views import home1
print (type(home)) --> <class 'function'>
print (type(home1)) --> <class 'flask.blueprints.Blueprint'>
As home1 registers correctly as a Blueprint but home does not I suspect that
there is a name collision but I don't know how to resolve it despite looking into
this excellent article on importing conventions.
As a result, when I try to register my blueprints with the app
this will work:
app.register_blueprint(home1, url_prefix='/home1') --> Fine
but this won't:
app.register_blueprint(home, url_prefix='/home')
--> AttributeError: 'function' object has no attribute 'name'
Why not just go along with using home1?
I want to understand how the collision can be resolved
I want to be able to use route names that are the same as the filename they are in like so:
frontend/views/home.py
from flask import Blueprint, render_template
home = Blueprint('home', __name__)
#home.route('/')
def home():
pass
I think your views/__init__.py file is causing this issue. It's making python assume your home.py file is a module to be imported. I believe the line from frontend.views import home is trying to import the home.py file rather than your intended home.home Blueprint.
Here's a working example:
/app.py
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
/app/__init__.py
from flask import Flask
def create_app():
app = Flask(__name__)
from .bp import bp
app.register_blueprint(bp)
return app
/app/bp/__init__.py
from flask import Blueprint
bp = Blueprint('bp', __name__, template_folder='templates')
from . import views
/app/bp/views.py
from app.bp import bp
#bp.route('/helloworld')
def helloworld():
return "hello world"
Try to use Capital letters in the Blueprint Module.
also you can use the url_prefix in the module.
Home = Blueprint("Home", __name__, url_prefix="/home")
#Home.route("/")
def home():
pass

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.

My hello world flask program is not running?

I'm a beginner in Flask, And i'm trying to create a simple hello world program but it's giving me errors on everytime with Undefined variable from import: run.
Here is my directory looks like:
/MyApplicationName:
/app
/__init__.py
/views.py
/run.py
My __init__.py is:
from flask import Flask
app = Flask(__name__)
import views
Here is my views.py:
from app import app
#app.route("/")
#app.route("/index")
def main():
return "Hello Flask!!"
Here is my last one run.py:
from app import app
if __name__ == "__main__":
app.run(debug=True)
Every time it gives me this error:
Undefined variable from import: run.
HELP WOULD BE APPRECIATED
Move:
from flask import Flask
app = Flask(__name__)
to views.py. Then make __init__.py:
from views import app
You have a circular import, but I'm not exactly sure as to why it's throwing the error it's throwing.
Have a look at flask-script, anyway evaluate to use a factory, something like create_app() that returns an app object.
It seems to be the common practice when using flask:
def create_app():
app = Flask(
'portal', static_folder='static/build', static_url_path='/static'
)
init_config(app)
init_login(app)
init_csrf(app)
app.register_blueprint(views)
return app
Without changing a single line of what you've coded, just move run.py out of the app directory.
Your project directory should look then like this:
└── MyApplication
├── __init__.py
├── app
│   ├── __init__.py
│   ├── views.py
└── run.py
Happy coding,
J.

Get debug status out of Flask Script Manager

I'm using Flask-Script and I've got a manage.py that looks like this.
from mypackage import create_app
from flask.ext.script import Manager
app = create_app()
manager = Manager(app)
if __name__ == '__main__':
manager.run()
I'll start my app with python manage.py runserver --debug
From within manage.py, how can I find out that runserver was called with --debug?
I've tried app.debug but that returns False and manager.get_options() returns an empty list.
The code you've provided is fine-- here's a mypackage.py file to demonstrate that:
from flask import Flask, Blueprint, current_app
test = Blueprint('user', __name__, url_prefix='/')
#test.route('/')
def home():
return str(current_app.debug)
def create_app():
app = Flask(__name__)
app.register_blueprint(test)
return app
Adding --debug reflects accurately (True) when you access the index page.

Categories