Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask SQLAlchemy: How to extend the base Model class?

In Flask/SQLAlchemy, we use the Model class from flask_sqlalchemy instead of from sqlalchemy, like this:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

class Foo(db.Model):
    bar = db.Column(db.String)

I have a function that I add to every Model I define. I want to extend some base class and add the function there so I don't have to repeat myself. With normal SQLAlchemy we can extend the declarative base class to do this. How can we achieve this in flask_sqlalchemy ?

Extending from the db.Model class doesn't work without raising:

InvalidRequestError: Class does not have a table or tablename specified and does not inherit from an existing table-mapped class.

like image 221
Matthew Moisen Avatar asked May 29 '16 23:05

Matthew Moisen


1 Answers

You can fix the error by setting __abstract__ = True. I modified your example:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

class Foo(db.Model):
    __abstract__ = True
    bar = db.Column(db.String)

__abstract__ is described in the documentation. Alternatively, you can use a mixin class.

Requiring more code, you can also override the declarative base class by subclassing SQLAlchemy and overriding its make_declarative_base() method. Example:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy, Model, _BoundDeclarativeMeta, _QueryProperty
from sqlalchemy.ext.declarative import declarative_base

app = Flask(__name__)

class MyModel(Model):
    ...

class MySQLAlchemy(SQLAlchemy):
    def make_declarative_base(self, metadata=None):
        base = declarative_base(cls=MyModel, name='MyModel',
                                metadata=metadata,
                                metaclass=_BoundDeclarativeMeta)
        base.query = _QueryProperty(self)
        return base

db = MySQLAlchemy(app)

and then subclassing db.Model "as usual".

like image 91
Manuel Jacob Avatar answered Nov 07 '22 13:11

Manuel Jacob