12

I basically just need to know how to query by excluding selected columns. Is this possible?

Example: I have table which has id, name, age, address, location, birth, age, sex... etc.

Instead of citing out the columns to retrieve, I'd like to just exclude some columns in the query(exclude age for example).

Sample code:

db.session.query(User.username).filter_by(username = request.form['username'], password = request.form['password']).first()

Last thing I wanna do is to list down all the attributes on the query() method, since this would be pretty long especially when you have lots of attributes, thus I just wanna exclude some columns.

1
  • 1
    If you're using marshmallow to serialize data, then in the Meta class of the ModelSchema, you can specify a tuple, called exclude to, well, exclude the specified fields from the serialized output. For example: exclude = ('field1', 'field2', ..., 'fieldN'). Commented Oct 4, 2019 at 18:31

4 Answers 4

17

Not sure why you're not just fetching the model. When doing that, you can defer loading of certain columns so that they are only queried on access.

db.session.query(User).options(db.defer('location')).filter_by(...).first()

In this example, accessing User.location the first time on an instance will issue another query to get the data.

See the documentation on column deferral: https://docs.sqlalchemy.org/en/20/orm/queryguide/columns.html

Note that unless you're loading huge amounts of data, you won't see any speedup with this. It might actually make things slower since another query will be issued later. I have queries that load thousands of rows with eager-loaded relationships in less than 200ms, so this might be a case of premature optimization.

Sign up to request clarification or add additional context in comments.

Comments

1

We can use the Inspection API to get the model's columns, and then create a list of columns that we want.

exclude = {'age', 'registration_date'}
insp = sa.inspect(User)
include = [c for c in insp.columns if c.name not in exclude]

# Traditional ORM style    
with Session() as s:
    q = s.query(*include)
    for row in q:
        print(row.id, row.name)
    print()

# 1.4 style
with Session() as s:
    q = sa.select(*include)
    for row in s.execute(q):
        print(row.id, row.name)
    print()

inspect returns the mapper for the model class; to work with non-column attributes like relationships use one of the mapper's other attributes, such as all_orm_descriptors.

Comments

1

If you're using an object deserializer like marshmallow, it is easier to omit the required fields during the deserialization. https://marshmallow.readthedocs.io/en/latest/api_reference.html#marshmallow.EXCLUDE

The fields to be omitted can be formed dynamically and conditionally excluded. Example:

ModelSchema(exclude=(field1, field2,)).jsonify(records)

Comments

-1

I am not aware of a method that does that directly, but you can always get the column keys, exclude your columns, then call the resulting list. You don't need to see what is in the list while doing that.

q = db.session.query(blah blah...)

exclude = ['age']
targ_cols = [x for x in q.first().keys() if x not in exclude]

q.with_entities(targ_cols).all()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.