Matthew Moisen
Matthew Moisen

Reputation: 18329

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.

Upvotes: 5

Views: 5612

Answers (1)

Manuel Jacob
Manuel Jacob

Reputation: 2014

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".

Upvotes: 11

Related Questions