Skip to content

Instantly share code, notes, and snippets.

@inklesspen
Last active February 21, 2017 02:35
Show Gist options
  • Save inklesspen/432cdf23439ac2290c80 to your computer and use it in GitHub Desktop.
Save inklesspen/432cdf23439ac2290c80 to your computer and use it in GitHub Desktop.

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

@inklesspen
Copy link
Author

I think it looks better with a space before the slash, like so:

    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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment