2

Context:

  • Python 3.6
  • flask
  • flask_restful
  • flask_sqlalchemy

Objective: Create database tables before the first request to the flask restful api, avoiding circular dependency between models.

Problem: When I do the first resquest, @app.before_first_request is called as expected, but It seems to be considering the includes with circular dependendy:

File "./app.py", in create_tables
    from models.uf_model import UfModel
File "home/server/models/uf_model.py", in <module>
    from models.cidade_model import CidadeModel
File "/home/server/models/cidade_model.py", in <module>
    from models.uf_model import UfModel
ImportError: cannot import name 'UfModel'

MY QUESTION: Even using app_context(), as suggested in similar questions, the circular dependency was not solved. How to fix it? What am I doing wrong?

My code:

db.py:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

uf_model.py One uf has many cidades

from db import db, filter_query
from datetime import datetime
from models.cidade_model import CidadeModel

class UfModel(db.Model):

    __tablename__ = 'uf'

    unfe_id = db.Column(db.Integer, primary_key=True)

    cidades = db.relationship('CidadeModel', backref='unfe_cidades', lazy=True, uselist=False)

To easily find all the cidades of a given uf, I've created that relationship.

cidade_model.py One cidade has just one uf

from db import db, filter_query
from datetime import datetime

from models.uf_model import UfModel

class CidadeModel(db.Model):

    __tablename__ = 'cidade'

    cida_id = db.Column(db.Integer, primary_key=True)

    cida_unfe_id = db.Column(db.Integer, db.ForeignKey('uf.unfe_id'), nullable=False, index=True)

    uf = db.relationship('UfModel')

To easily find the uf of a given cidade, I've created that relationship.

app.py:

from db import db

app = Flask(__name__)
api = Api(app)

@app.before_first_request
def create_tables():

    with app.app_context():
        from models.uf_model import UfModel
        from models.cidade_model import CidadeModel
        db.create_all()

if __name__ == '__main__':

    # some resources api.add_resource
    db.init_app(app)
Carlos Ost
  • 492
  • 7
  • 22
  • What is your question? What happens when you run this code? What error do you get? – Code-Apprentice Sep 09 '19 at 18:08
  • I thought everything was on the question. The objective is what I want to do. The problem is what happens when I run the code. But ok, I will edit and try to make it more clear. – Carlos Ost Sep 09 '19 at 18:10
  • Yes, in my first reading, I missed the error output in your post. However, you haven't clearly stated a question. – Code-Apprentice Sep 09 '19 at 18:12
  • Related: https://stackoverflow.com/questions/894864/circular-dependency-in-python – Code-Apprentice Sep 09 '19 at 18:12
  • I just want to say that your in your original draft everything was laid out very clear. I wish there were more questions on SO that were organized as well as yours is here. The question section that you added ties it all together. – Code-Apprentice Sep 09 '19 at 19:29

1 Answers1

1

You've got 2 ways to define relationships in models, either you reference the model class itself or you use the class name (the latter was added to avoid such circular dependency problem).

Since you've define the relationship with strings (e.g: uf = db.relationship('UfModel') in cidade_model.py), you don't need to import from models.uf_model import UfModel anymore. The same goes for CidadeModel in uf_model.py. You aren't using the imported class so you can just remove the import line.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
bagerard
  • 5,681
  • 3
  • 24
  • 48