A SQLAlchemy query is a generative object that you keep obtaining a modified copy of with successive method calls. Often, the final method call executes the query and returns a value. Python's built-in line continuation can obscure the structure, so explicitly use \
here.
Instead of this:
return db_session.query(Opportunity.id).filter(Opportunity.is_complete == sa.sql.true(),
Opportunity.created_by_id == flask.session.user_id,
Opportunity.is_staff_created == sa.sql.false()).count()
Do this:
return db_session.query(Opportunity.id)\
.filter(Opportunity.is_complete == sa.sql.true(),
Opportunity.created_by_id == flask.session.user_id,
Opportunity.is_staff_created == sa.sql.false())\
.count()
Note how the .count()
is on its own line at the end of the query. When you use .count()
, .all()
, or any other method that returns a result instead of a modified query, always put it on its own line so it's easy to see.
However, if the entire query fits on a single line and the result is assigned to a variable that isn't named something like query
, then it's okay to not put the executing method call on its own line. Example:
user = request.db_session.query(User).filter_by(public_id=public_id).one()
PEP8 instructs us to compare against None
by using the is
and is not
comparisons. This is because classes are free to define the ==
behavior however they wish, and this could mean that some_obj == None
would differ from None == some_obj
.
However, the is
and is not
comparisons do not work when constructing SQLAlchemy queries, for precisely the reason that classes cannot override those comparisons; SQLAlchemy overrides the other operators to have them return expression objects instead of a boolean value. Yet, Flake8 complains when you use MyModel.some_col == True
. SQLAlchemy provides a workaround here: MyModel.some_col == sqlalchemy.sql.true()
(and corresponding false()
and null()
calls).
I think it looks better with a space before the slash, like so: