I have the following app structure. IDE works fine, resolves, but running some scripts gives me
File "/home/sink/TARET/app/models.py", line 4, in <module>
from app import db
ImportError: No module named app
error. I call the module as:
import datetime
from app import db
class Role(db.Model):
__tablename__ = 'role'
RoleID = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.String(80), unique=True)
ModifiedDate = db.Column(db.DATETIME) and so on
What is the correct usage of modules in python?
I have the following structure.
Ok edit:
db is defined in init.py as
app = Flask(__name__)
app.debug = True
app.config.from_object('config')
db = SQLAlchemy(app)
On the bottom of your app/__init__.py put this:
from app import models
Why?
From http://flask.pocoo.org/docs/patterns/packages/
Circular Imports
Every Python programmer hates them, and yet we just added some:
circular imports (That’s when two modules depend on each other. In
this case views.py depends on __init__.py). Be advised that this is a
bad idea in general but here it is actually fine. The reason for this
is that we are not actually using the views in __init__.py and just
ensuring the module is imported and we are doing that at the bottom of
the file.
Related
I am writing a script that during development should delete the database and populate it with some dummy values. Unfortunately, the drop_all() part of it does not work:
from flask_sqlalchemy import SQLAlchemy
from my_app import create_app
from my_app.models import Block
db = SQLAlchemy()
def main():
app = create_app()
db.init_app(app)
with app.app_context():
db.session.commit()
db.drop_all() # <- I would expect this to drop everything, but it does not
db.session.commit()
db.create_all() # <- This works even if the database is empty
b1 = Block(name="foo")
db.session.add(b1) # <- Every time I run the script, another copy is added
db.session.commit()
blocks = Block.query.all()
for b in blocks:
print(b) # <- this should contain exactly one record every time, but keeps getting longer
And my_app.models.py contains:
from . import db
class Block(db.Model):
__tablename__ = "block"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30))
The drop all does apparently not drop the right tables. Examples I find on SO and other sources tend to feature class definitions in the same file, based on db.Model within the same file (such as here), which I cannot do. Do I need to somehow bind the imported classes to db? If so, how?
After some more searching I found the answer: instead of db = SQLAlchemy() in the script, I had to import it like in the models part: from my_app import db. Any explanation of this would be highly appreciated.
I can not even get off the ground with this one. Flask is not my first framework, but it is new to me since so many updates have went by. ok, so my problem is that I am running into this error when I am running my python file within the cli to import the db variable to work with it using sqlite.
>>> from __init__ import db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\*myusername*\Desktop\*appname*\__init__.py", line 2, in <module>
from sqlalchemy import SQLAlchemy
ImportError: cannot import name 'SQLAlchemy' from 'sqlalchemy' (C:\Users\*myusername*\Envs\*appname*\lib\site-packages\sqlalchemy\__init__.py)
My code is listed below, it isn't much but this is all I like from finishing my project. If anyone has any pointers here let me know. I am guessing it's something simple (it usually is) that I am just overlooking.
from flask import Flask, render_template
from sqlalchemy import SQLAlchemy
app = Flask('*appname*')
# Database functionality
app.config['SQLALCHEMY_DATABASE_URI']= 'sqlite:///C:/Users/*myusername*/Desktop/*appname*/'
db = SQLAlchemy(app)
class usersTable(db.Model):
userid = db.Column(db.Integer, primary_key=True)
fname = db.Column(db.Text)
lname = db.Column(db.Text)
email = db.Column(db.LargeBinary)
username = db.Column(db.LargeBinary)
password = db.Column(db.LargeBinary)
joined = db.Column(db.Date)
Thanks in advance guys. Normally my backend language is PHP, so I am branching out and this is really starting to get on my nerves lol.
First you need to install Flask-SQLAlchemy library using: pip install flask-sqlalchemy
Then import it like this in your code, from flask_sqlalchemy import SQLAlchemy
If you want to learn more, check this minimal application using flask-sqlalchemy.
I've had a look at a very similar issue, but the solution isn't working for me, and I was wondering if I could get some guidance.
This is my application structure:
mosiman/
__init__.py
blog/
__init__.py
blogconfig.py
blog.py
static/
...
templates/
...
I really wanted a way to build separate apps but manage them from one application instance so I wouldn't have to touch the WSGI layer, and blueprints seemed like the best way.
Here's what I think the relevant files are:
# mosiman/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import blog.blog as blog
...
...
db = SQLAlchemy()
...
...
def create_app():
app = Flask(__name__)
db_path = os.path.join(os.path.dirname(__file__), 'mosiman.db')
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///{}'.format(db_path)
app.config["SQLALCHEMY_BINDS"] = {'blog': os.path.join(os.path.dirname(__file__), 'blog/blog.db')
db.init_app(app)
app.register_blueprint(blog.blog, url_prefix='/blog')
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
I also have in my mosiman/blog/blog.py file:
#mosiman/blog/blog.py
<<< all of the usual flask imports and SQLAlchemy, etc >>>
from .__init__ import db
blog = Blueprint('blog', __name__)
...
...
class Entry(db.Model):
__bind_key__ = "blog"
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(150))
...
...
Here is my problem: I actually don't have a "default" database, so I have no classes for it. But I do want to initialize my blog database with the class Entry.
The default procedure for initializing the database seems to be to pop into the python REPL, import the database, and run db.create_all()
Well, I can't just import db and run db.create_all() because db hasn't been attached to an app yet (done in create_app()) This is how I proceed:
# pop open a REPL at mosiman/
>>> from __init__ import db
>>> from __init__ import create_app
>>> app = create_app()
>>> db.init_app(app)
>>> from blog.blog import Entry
>>> db.init_app(app)
# At this point, db still isn't attached to an engine?
>>> db
<SQLAlchemy engine=None>
>>> with app.app_context():
... db.create_all()
...
>>>
Now, when I go to mosiman/blog/ I find that blog.db has been created, but when I check the schema and tables in SQLite3 nothing turns up.
1 solved their problem by changing from __init__ import db to from mosiman import db
If I try to do that inside mosiman/:
>>> from mosiman import db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'mosiman'
even though I've got an __init__.py in there.
If I run it from ../ (the directory above mosiman):
>>> from mosiman import db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/users/d49chan/mosiman/__init__.py", line 3, in <module>
import blog.blog as blog
ModuleNotFoundError: No module named 'blog'
I'm not sure how to proceed. Maybe it's because I need sleep, but I've been trying to understand why nothing works for the past many hours. If you could point me in the right direction or possibly clear up some of my misunderstandings I'd be very grateful.
1) You don't namely import __init__.py. You should import it with the name of the directory (package) it's in.
2) You shouldn't import like this: import blog.blog. Instead you should: from blog import blog.
3) Be sure you have an __init__.py file in every directory so that the python importer can treat it as a package (directory) it can import from.
4) There's a difference between relative importing and absolute importing.
Relative importing:
# l3_module.py in l3_package
from ..l1_package import l1_module
This imports a module located two packages (directories) up in relation to the module importing it.
Now assuming l3_package is in an l2_package which is in an l1_module, You can also import it as such
Absolute importing:
# l3_moudle.py in l3_package
from l1_package import l1_module
This will also work, but then it sometimes messes stuff up, depending on your env.
Here's an excellent answer that can clear some stuff up for you: Relative imports for the billionth time.
Hope that helped :)
My project:
project_name
|- my_app
|- __init__.py
|- run.py
|- models.py
First example
run.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
from models import User
db.create_all()
if __name__ == '__main__':
app.run()
models.py
from run import db
class User(db.Model):
#...
__ init.py __ is empty
After running this example I get this error:
ImportError: cannot import name User
This error describe Circular import of app variable in models.py (as I understand).
Second example
run.py
from my_app import app
if __name__ == '__main__':
app.run()
models.py
from my_app import db
class User(db.Model):
#...
__ init.p __
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
from models import User
db.create_all()
And now all works correct.
And, at this point, I don't understand, why the same code give me different logic?
Where is the magic? Why Circular import in __ init.py __ does't throw an error?
Thank You!
I'm just going to talk about your first example, because you can actually reproduce both scenarios without changing the code:
Example 1: Run run.py directly to see the Import error
Example 2: Open a python repl, and run:
from run import app
app.run()
And your first example now works, for the same reason your second code example did: the imports were moved out of __main__
In example 1, run.py is the top level execution environment, and the code here runs in __main__. The relative import to models.py requires that all references in models.py be resolved (since the class you're importing from models.py may be dependent on other parts of models.py outside of the class itself). The first thing models.py does is go back to __main__ to perform a relative import of db, and since it needs to resolve all references, it does - and one of the references it tries to resolve is the original from models import user statement. Voila, ImportError.
The thing is, at this point run.py hasn't finished executing, and so far it's still trying to import the definition of User. But now models.py is trying to call into it as though it had finished loading, and it expects run.py to already know the definition of User, even though it's right in the middle of trying to figure that exact thing out!
This isn't a circular import - not really. models.py is just trying to import from a file that hasn't finished executing yet, and whose contents aren't available for use.
By moving __main__ elsewhere - into the repl, or by moving your code around so that run.py doesn't define anything - you're giving the code a chance to actually resolve all the dependencies before any code tries to use them. By using from run import app; app.run(), this is the only code that is not done executing. The imports themselves all get to complete their work, resolve their dependencies and make them available to __main__
tl;dr don't accidentally write code that imports from __main__ when __main__ doesn't yet know the things it's being asked for
I've decided to write a small webapp using Flask, postgresql and leaflet. I wanted to store coordinates (latitude and longitude) using PostGIS extender for postgresql. My flask application uses Flask-SQLAlchemy, blueprint and especially Flask-Migrate for the database migration process.
Here is an excerpt of my database model:
from . import db
from geoalchemy2 import Geometry
class Station(db.Model):
__tablename__ = 'stations'
id = db.Column(db.Integer, primary_key=True, unique=True)
name = db.Column(db.String(255))
position = db.Column(Geometry('Point', srid=4326))
Here an excerpt of my app/init.py
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import config
db = SQLAlchemy()
migrate = Migrate()
def create_app(config_name=None, main=True):
if config_name is None:
config_name = os.environ.get('FLASK_CONFIG', 'development')
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)
migrate.init_app(app, db)
from .home import home as home_blueprint
app.register_blueprint(home_blueprint)
from .admin import admin as admin_blueprint
app.register_blueprint(admin_blueprint, url_prefix='/admin')
return app
Before trying to use the specific extender, I didn't have any issue to adapt my model. Since then, the migration is doing alright but the upgrade doesn't work (python manage.py db upgrade).
Here the log I obtain from the webserver:
sa.Column('position', geoalchemy2.types.Geometry(geometry_type='POINT', srid=4326), nullable=True),
`enter code here`NameError: name 'geoalchemy2' is not defined
I'm a bit lost and I didn't find much help on this specific subject. Any idea on what might cause this issue?
Alembic does not try to determine and render all imports for custom types in the migration scripts. Edit the generated script to include from geoalchemy2.types import Geometry and change the column def to just use Geometry.
You should always review the auto-generated scripts before running them. There's even comments in the script saying so.
Another way to do this which doesn't require manually editing the revision is adding import geoalchemy2 into alembic/script.py.mako and then alembic adds the module every time.
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from alembic import op
import sqlalchemy as sa
import geoalchemy2 # <--- right here
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
def upgrade():
${upgrades if upgrades else "pass"}
def downgrade():
${downgrades if downgrades else "pass"}