Sorting records
To return rows in order, use the order_by()
method:
- >>> for t in Tweet.select().order_by(Tweet.created_date):
- ... print(t.pub_date)
- ...
- 2010-01-01 00:00:00
- 2011-06-07 14:08:48
- 2011-06-07 14:12:57
- >>> for t in Tweet.select().order_by(Tweet.created_date.desc()):
- ... print(t.pub_date)
- ...
- 2011-06-07 14:12:57
- 2011-06-07 14:08:48
- 2010-01-01 00:00:00
You can also use +
and -
prefix operators to indicate ordering:
- # The following queries are equivalent:
- Tweet.select().order_by(Tweet.created_date.desc())
- Tweet.select().order_by(-Tweet.created_date) # Note the "-" prefix.
- # Similarly you can use "+" to indicate ascending order, though ascending
- # is the default when no ordering is otherwise specified.
- User.select().order_by(+User.username)
You can also order across joins. Assuming you want to order tweets by theusername of the author, then by created_date:
- query = (Tweet
- .select()
- .join(User)
- .order_by(User.username, Tweet.created_date.desc()))
- SELECT t1."id", t1."user_id", t1."message", t1."is_published", t1."created_date"
- FROM "tweet" AS t1
- INNER JOIN "user" AS t2
- ON t1."user_id" = t2."id"
- ORDER BY t2."username", t1."created_date" DESC
When sorting on a calculated value, you can either include the necessary SQLexpressions, or reference the alias assigned to the value. Here are twoexamples illustrating these methods:
- # Let's start with our base query. We want to get all usernames and the number of
- # tweets they've made. We wish to sort this list from users with most tweets to
- # users with fewest tweets.
- query = (User
- .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
- .join(Tweet, JOIN.LEFT_OUTER)
- .group_by(User.username))
You can order using the same COUNT expression used in the select
clause. Inthe example below we are ordering by the COUNT()
of tweet ids descending:
- query = (User
- .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
- .join(Tweet, JOIN.LEFT_OUTER)
- .group_by(User.username)
- .order_by(fn.COUNT(Tweet.id).desc()))
Alternatively, you can reference the alias assigned to the calculated value inthe select
clause. This method has the benefit of being a bit easier toread. Note that we are not referring to the named alias directly, but arewrapping it using the SQL
helper:
- query = (User
- .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
- .join(Tweet, JOIN.LEFT_OUTER)
- .group_by(User.username)
- .order_by(SQL('num_tweets').desc()))
Or, to do things the “peewee” way:
- ntweets = fn.COUNT(Tweet.id)
- query = (User
- .select(User.username, ntweets.alias('num_tweets'))
- .join(Tweet, JOIN.LEFT_OUTER)
- .group_by(User.username)
- .order_by(ntweets.desc())