4

This question is a simplification of "Filter relationships and paginate in Flask-SQLAlchemy", and an answer here would probably yield a solution there too.

Say I have a simple model class Design:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)

class Design(db.Model):
    __tablename__ = 'design'
    id = db.Column(db.Integer, primary_key=True)
    designname = db.Column(db.String(64))

I can get a Flask-SQLAlchemy BaseQuery object like this:

>>> Design.query
<flask_sqlalchemy.BaseQuery object at 0x7f0b29c63990>

And I can get data back as you would expect:

>>> Design.query.all()
[<item1>, <item2>, <item3>]

I can also get a BaseQuery object this way (which I think is necessary for more complex query, e.g., one with joins):

>>> db.Query(Design)
<flask_sqlalchemy.BaseQuery object at 0x7f0b29c6fdd0>

It looks like it should be the same object type - indeed, the SQL generated is identical:

>>> str(db.Query(Design)) ==  str(Design.query)
True

And yet, when I try the all() method here, it doesn't work:

>>> db.Query(Design).all()
Traceback (most recent call last):
File "<debugger>", line 1, in <module>
db.Query(Design).all()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2320, in all
return list(self)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2437, in __iter__
self.session._autoflush()
AttributeError: 'NoneType' object has no attribute '_autoflush'

EDIT: I believe the problem is that the second approach is not attaching a session to the BaseQuery object. The first method has one:

>>> Design.query.session
<flask_sqlalchemy.SignallingSession object at 0x7f0b29fbd510>

But the other approach does not:

>>> db.Query(Design).session is None
True

Any insight is much appreciated.

Community
  • 1
  • 1
Owen
  • 3,063
  • 5
  • 30
  • 26

1 Answers1

11

You should be able to use

db.session.query(Design).all()

session.query is how you would perform queries when using SQLAlchemy without Flask-SQLAlchemy.

UPDATE

To perform a join using Flask-SQLAlchemy's BaseQuery:

Design.query.join(YourOtherModel).all()
dirn
  • 19,454
  • 5
  • 69
  • 74
  • 1
    Yes, thank you, but I already know how to do this with a regular SQLAlchemy session. I am specifically trying to create a *flask*_SQLAlchemy BaseQuery using this alternative syntax. My reason for doing this is the same as the other SE question that I referenced - I want to use the Pagination provided in the BaseQuery class. I should have made that more clear on the question. – Owen Mar 01 '15 at 17:43
  • I guess I'm just unclear as to why you can't use `Design.query`. – dirn Mar 01 '15 at 19:25
  • If you can show me how to use the `Design.query` with a table join, that would be great and I'll accept the answer. The reason I was trying to get at via the session object is that I need to do a table join -- in pure SQLAlchemy, it would look like `db.session.query(Parent, Child).join(Child).all()` -- so I had hoped that I could do that with the flask extensions, something like `db.Query(Parent, Child.join(Child).all()`, but that doesn't work. My question is a simplification of this problem... what is flask's `db.Query` for anyway, if it doesn't return a session-bound object? – Owen Mar 01 '15 at 21:15
  • `Design.query.join(YourOtherModel).all()` – dirn Mar 01 '15 at 21:33
  • Yes, perfect. Thank you for the help with my admittedly beginner question. – Owen Mar 02 '15 at 11:43
  • FWIW, it looks like I fell into #7 of the [10 common stumbling blocks for SQLAlchemy newbies](http://alextechrants.blogspot.com/2013/11/10-common-stumbling-blocks-for.html) – Owen Mar 03 '15 at 01:05