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

How do I override the default query class? #232

Closed
nickretallack opened this issue Oct 22, 2014 · 10 comments
Closed

How do I override the default query class? #232

nickretallack opened this issue Oct 22, 2014 · 10 comments

Comments

@nickretallack
Copy link

I thought this should work, but it doesn't.

@davidism
Copy link
Member

As far as I know, you make a subclass of SQLAlchemy and override make_declarative_base. At least, that's what I do and it works fine.

@nickretallack
Copy link
Author

It's this stackoverflow post that lead me to believe I could do it this way.

@nickretallack
Copy link
Author

@davidism do you have an example of how to do this? It seems complicated.

@davidism
Copy link
Member

from flask_sqlalchemy import BaseQuery, Model, _BoundDeclarativeMeta, SQLAlchemy as BaseSQLAlchemy, _QueryProperty

class MyBaseQuery(BaseQuery):
    pass  # do stuff here

class MyModel(Model):
    # in this case we're just using a custom BaseQuery class, but you can add other stuff as well
    query_class = MyBaseQuery

class SQLAlchemy(BaseSQLAlchemy):
    def make_declarative_base(self):
        # in this case we're just using a custom Model class, but you can change the DelcarativeMeta or other stuff as well
        base = declarative_base(cls=MyModel, name='Model', metaclass=_BoundDeclarativeMeta)
        base.query = _QueryProperty(self)
        return base

db = SQLAlchemy()

@davidism
Copy link
Member

Actually, this isn't a full solution, as relationships won't get the custom class. See https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L73 which is hard-coded to use the default BaseQuery.

@nickretallack
Copy link
Author

It'd be cool if there was an easier way to do this. Like a single option I could set when instantiating SQLAlchemy.

@MerliX
Copy link

MerliX commented Dec 2, 2014

There is a big importance of ability to change default query class. I use flask-sqlalchemy with mysql, and used to customize count() function for sqlalchemy (by default it produces very slow SQL (link) ). I inherited BaseQuery and fixed count(), used all approaches discussed here, but i still have slow counts using db.relationship(). There is an option to set db.backref with 'query_class' param, but no option for db.relationship

@noah
Copy link

noah commented Feb 27, 2015

+1 basically I need to be able to write custom pagintion that does not encounter exponential complexity when using LIMIT and OFFSET. See:

http://stackoverflow.com/questions/16916633/if-postgresql-count-is-always-slow-how-to-paginate-complex-queries
http://stackoverflow.com/questions/6618366/improving-offset-performance-in-postgresql

With hard-coded Query class this is badly broken for all but the most trivial applications.

@justanr
Copy link
Contributor

justanr commented May 8, 2015

Hm. Simply allowing setting a query_class parameter in __init__ and passing it down to _include_sqlalchemy (and ultimately _set_default_query_class) goes most of the way towards fixing an issue like this. However, Model would still hard code the query class as BaseQuery and doing something like...

class SQLAlchemy:
    def __init__(self, query_class=BaseQuery...):
        self.Model = self.make_declarative_base(...)
        # works but you know :/
        self.Model.query_class = query_class

example of this sort of change

@immunda
Copy link
Contributor

immunda commented Jun 9, 2015

Thanks @justanr, helpful example.

This issue has now been eaten by #319 and prioritised.

@immunda immunda closed this as completed Jun 9, 2015
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

6 participants