Joining on arbitrary fields

If a foreign key does not exist between two tables you can still perform ajoin, but you must manually specify the join predicate.

In the following example, there is no explicit foreign-key between User andActivityLog, but there is an implied relationship between theActivityLog.object_id field and User.id. Rather than joining on a specificField, we will join using an Expression.

  1. user_log = (User
  2. .select(User, ActivityLog)
  3. .join(ActivityLog, on=(User.id == ActivityLog.object_id), attr='log')
  4. .where(
  5. (ActivityLog.activity_type == 'user_activity') &
  6. (User.username == 'charlie')))
  7.  
  8. for user in user_log:
  9. print(user.username, user.log.description)
  10.  
  11. #### Print something like ####
  12. charlie logged in
  13. charlie posted a tweet
  14. charlie retweeted
  15. charlie posted a tweet
  16. charlie logged out

Note

Recall that we can control the attribute Peewee will assign the joinedinstance to by specifying the attr parameter in the join() method.In the previous example, we used the following join:

  1. join(ActivityLog, on=(User.id == ActivityLog.object_id), attr='log')

Then when iterating over the query, we were able to directly access thejoined ActivityLog without incurring an additional query:

  1. for user in user_log:
  2. print(user.username, user.log.description)