Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlalchemy-mixins incompatible with Flask-SQLAlchemy's custom model class recommendation. #34

Open
kkinder opened this issue Jan 27, 2020 · 5 comments

Comments

@kkinder
Copy link

kkinder commented Jan 27, 2020

This is a little convoluted to explain, but I've found that, sqlalchemy-mixin does not exactly work with Flask-SQLAlchemy as both are documented.

According to the Flask-SQLAlchemy docs, if you want to define your own base class, you pass it to SQLAlchemy(). For example:

from flask_sqlalchemy import Model


class MyModel(Model):
    @declared_attr
    def id(cls):
        return db.Column(db.Integer, primary_key=True, index=True)

db = SQLAlchemy(model_class=MyModel)

class Pet(db.Model):
    ...

Notice that you're inheriting from db.Model, not from MyModel. That's because, when I pass model_class to SQLAlchemy, it does some magic afterwards to actually add declarative_base() as a superclass and generates a final class that merges the two.

Why is this important, you ask? Consider this code block:

from flask_sqlalchemy import Model
from sqlalchemy_mixins import AllFeaturesMixin


class MyModel(Model. AllFeaturesMixin):
    @declared_attr
    def id(cls):
        return db.Column(db.Integer, primary_key=True, index=True)

db = SQLAlchemy(model_class=MyModel)

While I'm using AllFeaturesMixin and Flask-SQLAlchemy's Model class as recommended, I'll get an exception.

    return db.Column(db.Integer, primary_key=True, index=True)
NameError: name 'db' is not defined

The reason is that Flask-SQLAlchemy's SQLAlchemy() class does not expect a subclass from Base in Base = declarative_base(). It mixes in declarative base on its own.

That is to say, with straight Flask-SQLAlchemy, the part of the above code that resolves the declared_attr doesn't run until db is instanciated. But because sqlalchemy-mixins inherits directly from Base, its declared_attrs are resolved immediately and there's a NameError.

My general suspicion is that the solution is for sqlalchemy-mixins to perhaps be mixins, not subclasses of Base. But I'm not sure. At any rate, I thought I would bring up the issue for consideration. Thanks for the great library!

@phretor
Copy link

phretor commented Apr 5, 2020

@kkinder why do you do this?

class Pet(db.Model):

and not this:

class Pet(MyModel):

@kkinder
Copy link
Author

kkinder commented Apr 9, 2020

@phretor because I'm using Flask-SQLAlchemy and that's how you pull in its goodness.

@maximdeclercq
Copy link
Contributor

I managed to implement something like this as follows:

...
db = SQLAlchemy(app)

class BaseModel(db.Model, AllFeaturesMixin):
    __abstract__ = True

BaseModel.set_session(db.session)

class User(BaseModel):
    id = db.Column(db.Integer, primary_key=True)

I hope this works for you.

@lekhnath
Copy link

Did not work

@lekhnath
Copy link

Getting error:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants