Paul Steven
Paul Steven

Reputation: 41

Access db from a separate file flask SQLAlchemy python3

I am writing a flask application. I have two files. main.py and databases.py. I want to create a database from the database.py file. The main.py should access the databases.py file and create the database and table named "Users". But it shows import error. Help me with this issue

main.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from databases import User

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/data_log.db'
db = SQLAlchemy(app)

if __name__ == '__main__':
    db.create_all()
    app.run(host='0.0.0.0', port=5001)  

databases.py

from main import db
from passlib.apps import custom_app_context as pwd_context

class User(db.Model) :
    __tablename__ = 'users'
    user_id     =   db.Column(db.Integer, primary_key = True)
    username    =   db.Column(db.String(32), index = True)
    password    =   db.Column(db.String(128))
    def hash_password(self, password) :
        self.password =pwd_context.hash(password)
    def verify_password(self, password) :
        return pwd_context.verify(password, self.password)

Traceback:

Traceback (most recent call last):
  File "main.py", line 3, in <module>
    from databases import User
  File "/home/paulsteven/stack/databases.py", line 1, in <module>
    from main import db
  File "/home/paulsteven/stack/main.py", line 3, in <module>
    from databases import User
ImportError: cannot import name 'User'

Upvotes: 1

Views: 3465

Answers (1)

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

This is a regular case of cyclic imports conflict. The traceback gives you a clear steps:

How it goes in steps:

  • you run main.py
  • the control flow starts importing features/libraries till it gets the 3rd line from databases import User.
  • it goes to the databases module to find the needed User class. But ... the User may use the outer scope features (and it does require db.Model), so the control flow needs to scan databases module from the start. This reflects the 2nd step from traceback ("/home/paulsteven/stack/databases.py", line 1)
  • from the position of previous step being at database.py the control flow encounters from main import db - that means it should turn back to the main(main.py) module!
  • control flow returned to the main module start scanning again from the 1st line - till it finds from databases import User again. This reflects the traceback's 3rd step (File "/home/paulsteven/stack/main.py", line 3)
    • and you run into cycle ...

What is right way to solve the issue?
Keep all DB context/DB models in separate module(s).
Follow the sequence of objects relations and how they depend on each other:

---> Application instantiated first (app)

  • ---> then DB framework instance is created db = SQLAlchemy(app) depending on app

    • ---> then custom DB models created (like User(db.Model)) depending on db instance

main.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# from databases import User  <--- shouldn't be here

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/data_log.db'
db = SQLAlchemy(app)

if __name__ == '__main__':
    from databases import User  #  after instantiating `db` import model(s) 
    db.create_all()
    app.run(host='0.0.0.0', port=5001)  

Upvotes: 5

Related Questions