How to split Flask models from app.py without going through db object?

I would like to use Flask-Migrate and watch their example:

from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' db = SQLAlchemy(app) migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) if __name__ == '__main__': manager.run() 

This works great as a simple game example, but I have more than one model, and I don’t want to define models in this script as well as in what defines the code of my application. Thus, I want to output them to a model file, which I can split between them.

I am trying to do this by placing the User class in models.py and then importing the user from there. Unfortunately, this raises a NameError: name 'db' is not defined .

My question (s):

  • Do I need to use db = SQLAlchemy(app) in my models.py , and if it will be available in my migration script and the application itself?
  • If I cannot (or should not) put it in models.py , how can I use my models in my own file without going through db all over?
+6
source share
2 answers

Dividing such a small application into modules is difficult, because you will find many cases where the two modules you create must mutually import each other, creating circular dependencies.

I recommend that you look at how to properly structure a larger application using the app factory function and delayed initialization of all extensions. An example application that does this, Flasky , is shown in my book.

All that is said, you can divide the application into two parts, you just need to be careful where you place the import statements. In the example below, I decided to move the instance creation of db and User to the models.py file.

Here is the main application module:

 from flask import Flask from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' from models import db # <-- this needs to be placed after app is created migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) if __name__ == '__main__': manager.run() 

And here is models.py:

 from __main__ import app from flask.ext.sqlalchemy import SQLAlchemy db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) 

Here, the main module will create the app , and only then import models.py. When models.py tries to import the app from the main module, it is already created. If you move from models import db to the top of the file, others import this code.

+10
source

Here is an idea. You can create a model package in which you define classes as separate .py files. For example, user.py contains the User class.

In the __init__.py file, you can define the db variable. You can also include the from user import User statement so that you can access the User object directly outside the package. For example, you can import the model package to another location in the program using import model , and then use model.User to directly use the User class.

To use the db variable directly in user.py , use from ..model import db , which imports the db variable defined in the __init__.py file.

0
source

All Articles