Could anyone explain the difference between filter and filter_by functions in SQLAlchemy?
Which one should I be using?
- 14,556
 - 1
 - 47
 - 52
 
- 75,521
 - 93
 - 229
 - 319
 
5 Answers
filter_by is used for simple queries on the column names using regular kwargs, like
db.users.filter_by(name='Joe')
The same can be accomplished with filter, not using kwargs, but instead using the '==' equality operator, which has been overloaded on the db.users.name object:
db.users.filter(db.users.name=='Joe')
You can also write more powerful queries using filter, such as expressions like:
db.users.filter(or_(db.users.name=='Ryan', db.users.country=='England'))
- 15,462
 - 9
 - 79
 - 80
 
- 26,899
 - 12
 - 60
 - 88
 
- 
                    27How does this work under the hood? Would not `db.users.name=='Ryan'` evaluate once to a constant and then be meaningless from then on? It seems like one would need to use a lambda for this to work. – Hamish Grubijan Feb 27 '13 at 23:11
 - 
                    60the equality operator is overloaded – Daniel Feb 27 '13 at 23:12
 - 
                    12`type(model.column_name == 'asdf')` → `sqlalchemy.sql.elements.BinaryExpression` – Nick T May 22 '17 at 16:53
 - 
                    31Be careful when using `.filter`. a query like `id=12345`, `query(users).filter(id == id)` will not filter on `users.id`. Instead, it will evaluate `id == id` as `True` and return all users. You need to use `.filter(users.id == id)` (as demoed above). I made this mistake earlier today. – Feb 22 '19 at 23:00
 
We actually had these merged together originally, i.e. there was a "filter"-like method that accepted *args and **kwargs, where you could pass a SQL expression or keyword arguments (or both).  I actually find that a lot more convenient, but people were always confused by it, since they're usually still getting over the difference between column == expression and keyword = expression.  So we split them up.
- 9,880
 - 2
 - 38
 - 55
 
- 72,307
 - 23
 - 193
 - 185
 
- 
                    36I think your point about `column == expression` vs. `keyword = expression` is the key point to make about the difference between `filter` and `filter_by`. Thanks! – Hollister Dec 12 '10 at 18:03
 - 
                    This is a nice related question: [http://stackoverflow.com/questions/19506105/flask-sqlalchemy-query-with-keyword-as-variable]. – Soferio Sep 12 '14 at 14:10
 - 
                    3I'm new to sqlalchemy so excuse me if this is a stupid question, but filter_by() doesn't seem to allow for even the very simple conditions such as "price >= 100". So, why have filter_by() function anyway, if you only can use it for the very simplest condition such as "price = 100"? – PawelRoman Oct 12 '14 at 20:39
 - 
                    20
 - 
                    3Is there any performance difference between them? I was thinking that `filter_by` might be a bit faster than `filter`. – Devi Apr 30 '15 at 05:38
 - 
                    12The point of using `filter_by` is to be able to write jut the field name, for that class, no questions asked - while `flter` requires the actual column object - which usually will require one to type (and to read) at least a redundant class name. So, if one wants to filter by equality, it is rather convenient. – jsbueno May 18 '16 at 14:32
 - 
                    I like `filter_by` for building convenience functions into an app, which allow users to run simple queries by just passing in a table name and dictionary of equality filters. Beyond this, though, it's difficult to see why I wouldn't just use `filter`. – Todd Jun 09 '20 at 15:20
 - 
                    Sometime filter_by is trick, eg. filter_by(customer.created_time < some_time) it cannot select the correct value, for some reason, the `<` always got true. – Jaden May 23 '21 at 18:42
 
It is a syntax sugar for faster query writing. Its implementation in pseudocode:
def filter_by(self, **kwargs):
    return self.filter(sql.and_(**kwargs))
For AND you can simply write:
session.query(db.users).filter_by(name='Joe', surname='Dodson')
btw
session.query(db.users).filter(or_(db.users.name=='Ryan', db.users.country=='England'))
can be written as
session.query(db.users).filter((db.users.name=='Ryan') | (db.users.country=='England'))
Also you can get object directly by PK via get method:
Users.query.get(123)
# And even by a composite PK
Users.query.get(123, 321)
When using get case its important that object can be returned without database request from identity map which can be used as cache(associated with transaction)
- 109
 - 12
 
- 1,053
 - 9
 - 16
 
- 
                    These code examples are misleading: Declarative base table classes and instances have neither filter nor query methods; they use the session. – Turtles Are Cute Mar 16 '16 at 19:45
 - 
                    I reproduce `users.filter` from previous answer. And may be its my fault :) `query` attribute is [query_property](http://docs.sqlalchemy.org/en/latest/orm/contextual.html?highlight=query_property#sqlalchemy.orm.scoping.scoped_session.query_property) and its quite a standard sugar nowadays – enomad Mar 16 '16 at 21:47
 
filter_by uses keyword arguments, whereas filter allows pythonic filtering arguments like filter(User.name=="john")
- 9,304
 - 7
 - 42
 - 56
 
- 29,455
 - 6
 - 42
 - 51
 
Apart from all the technical information posted before, there is a significant difference between filter() and filter_by() in its usability.
The second one, filter_by(), may be used only for filtering by something specifically stated - a string or some number value. So it's usable only for category filtering, not for expression filtering.
On the other hand filter() allows using comparison expressions (==, <, >, etc.) so it's helpful e.g. when 'less/more than' filtering is needed. But can be used like filter_by() as well (when == used).
Just to remember both functions have different syntax for argument typing.
- 189
 - 2
 - 5