quechon quechon - 1 month ago 12
Python Question

importing issues between modules

|--------FlaskApp
|----------------FlaskApp
|----------------__init__.py
|----------------view.py
|----------------models.py
|----------------db_create.py
|-----------------------static
|-----------------------templates
|-----------------------venv
|-----------------------__init__.py
|----------------flaskapp.wsgi


this is my modules and folder layout i have a import problem in init i have
db = sqlalchemy
im trying to import db to views.py, models.py and db_create.py but im getting all kinds of importing errors because im not importing thr proper way now my question is if i want to import db to the modules i specified how would i do it without getting a error

some of the code importing db

models.py

from FlaskApp import db

class UserInfo(db.Model):

__tablename_ = 'user_info'

id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(80), unique=True)
password = db.Column(db.String(100), nullable=False)
posts = relationship('UserPosts', backref='posts')

def __init__(self, username, email, password):
self.username = username
self.email = email
self.password = password

def __repr__(self):
return '{}-{}'.format(self.username, self.email)


views.py

from FlaskApp import db

@app.route('/')
@login_required
def home():
user = db.session.query(UserInfo).all()
return render_template('home.html', user=user)


__init__.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)


tail /var/log/apache2/error.log
[Tue Oct 11 04:17:20.925573 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] Traceback (most recent call last):, referer: http://localhost/
[Tue Oct 11 04:17:20.925618 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] File "/var/www/FlaskApp/flaskapp.wsgi", line 14, in <module>, referer: http://localhost/
[Tue Oct 11 04:17:20.925626 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] from FlaskApp import app as application, referer: http://localhost/
[Tue Oct 11 04:17:20.925638 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] File "/var/www/FlaskApp/FlaskApp/__init__.py", line 4, in <module>, referer: http://localhost/
[Tue Oct 11 04:17:20.925644 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] import FlaskApp.main, referer: http://localhost/
[Tue Oct 11 04:17:20.925653 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] File "/var/www/FlaskApp/FlaskApp/main.py", line 7, in <module>, referer: http://localhost/
[Tue Oct 11 04:17:20.925658 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] from models import UserInfo, referer: http://localhost/
[Tue Oct 11 04:17:20.925668 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] File "/var/www/FlaskApp/FlaskApp/models.py", line 2, in <module>, referer: http://localhost/
[Tue Oct 11 04:17:20.925673 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] from FlaskApp import db, referer: http://localhost/
[Tue Oct 11 04:17:20.925707 2016] [wsgi:error] [pid 5049:tid 139870897813248] [client 174.58.31.189:55884] ImportError: cannot import name 'db', referer: http://localhost/


my goal is not just to solve one error is to be able to import the right way from now on

Answer

This is actually the most painful moment for a Flask learner. Basically, your FlaskApp is dependent on FlaskApp.main then FlaskApp.models and then back to FlaskApp which create a perfect case of circular dependency.

Here's the way which I think is elegant and pythonic, by attaching the db variable to app in __init__.py:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)
app.db = db

with app.app_context():
    import FlaskApp.main

In main.py:

from flask import current_app as app
from .models import UserInfo


@app.route('/')
@login_required     
def home():
    user = app.db.session.query(UserInfo).all()
    return render_template('home.html', user=user)

In models.py:

from flask import current_app as app

db = app.db


class UserInfo(db.Model):

    __tablename_ = 'user_info'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(80), unique=True)
    password = db.Column(db.String(100), nullable=False)
    posts = relationship('UserPosts', backref='posts')

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password

    def __repr__(self):
        return '{}-{}'.format(self.username, self.email)

Then you can use app.db or current_app.db inside of any functions/methods in your application and don't need to worry about the circular dependency.