Lets say I have a part of my Flask app that I want to pull out and use in multiple different projects. It has SQLAlchemy models using Flask-SQLAlchemy, as well as views and templates. I can get the app.route decorators by using a Module, but how can I handle the SQLAlchemy db object?
Since my component needs to be separate, I can't just import the db object. But I don't think I should create the db object twice. How would I mix its metadata in with the metadata in the rest of the project?
At first you must share metadata
and do not use flask-sqlalchemy db.Model as base for you re-usable app.
At second you must recreate all classes with extending them new bases from flask-sqlalchemy for supporting signals, short-cuts and other stuff.
Integrate bases (it may be buggy):
def integrate_models(cls, nbase):
new_bases = list(cls.__bases__) + [nbase]
new_dict = dict(cls.__dict__)
new_dict.update(dict(nbase.__dict__))
return type.__new__(cls.__class__, cls.__name__, tuple(new_bases), new_dict)
Example Flask app with sqlalchemy extension:
# -*- coding: utf-8 -*-
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
if __name__ == '__main__':
from some_model_base import init_metadata
init_metadata(db.Model.metadata)
from some_model import SomeClass
SomeClass = integrate_models(SomeClass, db.Model)
db.create_all()
print SomeClass.query.all()
Where some_model_base.py:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
def init_metadata(metadata):
Base.metadata = metadata
And some_model.py:
from sqlalchemy import Column, Integer, String
from some_model_base import Base
class SomeClass(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
In this example tested only db.create_all and SomeClass.query shortcut.
Sorry for my poor English.
You should use flask.current_app
, it is a proxy object to access the current application, and it is what is used in some extensions. So, your code would look something like this:
from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(current_app)
and then use your db
object as you would usually do. But i'm not sure if this would work if the user used your module and also needed to use flaskext.sqlalchemy
, maybe it would conflict, i'd suggest to test this, to be sure your module will be 100% compatible with any flask
application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With