2
backend
├── erp
│   ├── blueprint_create_order_and_add_products
│   │   ├── __init__.py
│   │   └── resources
│   │       ├── create_order.py
│   │       ├── __init__.py
│   ├── blueprint_general_query
│   │   ├── __init__.py
│   │   └── resources
│   │       ├── general_query.py
│   │       └── __init__.py
│   ├── common
│   │   ├── __init__.py
│   │   └── models
│   │       ├── brand.py
│   │       ├── productwithspecs.py
│   ├── database_collection
│   │   ├── finance.db
│   │   ├── orders.db
│   │   └── vendors.db
│   └── __init__.py
├── __init__.py
└── run.py

Above is sort of my app structure The models folder have db classes, the problem is that the class in brand module involves (through relationship) and imports the class in productwithspecs module, and there are lots of related db classes. How to import them in a CRUD resource of flask restful without circular imports.

The structure of app.py is:

from erp import app

if __name__ == '__main__':
    app.run(debug=True)

the code of erp/ini.py is:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db"

db = SQLAlchemy(app)
ma = Marshmallow(app)

from erp.blueprint_create_order_and_add_products import bp as bp1 # api_createorders_addproducts

# REGISTER blueprint apis to app
app.register_blueprint(bp1)

Please let me know how to avoid circular imports, as I will be needing to import db classes into resources folder in blueprints e.g create_order module etc. Thanks

1 Answers1

3

You should use an Application Factory App. You find the official recommendation here and this is a good tutorial.

After refactoring your erp/__init__.py should look similar to:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)

db = SQLAlchemy(app)
ma = Marshmallow(app)

def create_app():
    db.init_app(app)
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db"
    ma.init_app(app)

    with app.app_context():
        # Include your routes here

        app.register_blueprint(erp.blueprint_create_order_and_add_products.bp)

    return app

Your app.py:

from erp import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

And from all other modules you can import like this:

from erp import app, db
above_c_level
  • 3,579
  • 3
  • 22
  • 37
  • thanks a lot. Can you please explain what does a "factory" means as in "application factory". I googled but couldnt understand what application factory means / its purpose / how it helps. Thanks in advance – Arsalan Ahmad Ishaq Apr 08 '20 at 07:11
  • "Factory" means you can produce as many app objects as you like, e.g. app1 = create_app(); app2 = create_app(). If a car factory churns out cars, the Application Factory churns out applications. More important than creating my applications is the separation of the app without any configuration and the specific app returned from create_app(). I hope this explanation makes at least some sense. – above_c_level Apr 08 '20 at 14:05
  • thanks, but what would be a good use for creating multiple apps which are almost exact same since we are not building other resources / endpoints / db classes etc? – Arsalan Ahmad Ishaq Apr 08 '20 at 14:11
  • I am using it for testing. I have several configurations (prod, dev, test). My test configuration uses another database as my prod/dev configuration. With a factory I don't have to duplicate my code. I just call create_app(config='test'). You just need to differentiate the configs in your create_app. Btw, a good source for testing is [AJ Pryor's best practices](http://alanpryorjr.com/2019-05-20-flask-api-example/) – above_c_level Apr 08 '20 at 14:59
  • yours very different than the link provided. I'm confused – greendino Aug 29 '22 at 04:12