Model definitions

We’ll use the following model definitions for our examples:

  1. import datetime
  2. from peewee import *
  3. db = SqliteDatabase(':memory:')
  4. class BaseModel(Model):
  5. class Meta:
  6. database = db
  7. class User(BaseModel):
  8. username = TextField()
  9. class Tweet(BaseModel):
  10. content = TextField()
  11. timestamp = DateTimeField(default=datetime.datetime.now)
  12. user = ForeignKeyField(User, backref='tweets')
  13. class Favorite(BaseModel):
  14. user = ForeignKeyField(User, backref='favorites')
  15. tweet = ForeignKeyField(Tweet, backref='favorites')

Peewee uses ForeignKeyField to define foreign-key relationships between models. Every foreign-key field has an implied back-reference, which is exposed as a pre-filtered Select query using the provided backref attribute.

Creating test data

To follow along with the examples, let’s populate this database with some test data:

  1. def populate_test_data():
  2. db.create_tables([User, Tweet, Favorite])
  3. data = (
  4. ('huey', ('meow', 'hiss', 'purr')),
  5. ('mickey', ('woof', 'whine')),
  6. ('zaizee', ()))
  7. for username, tweets in data:
  8. user = User.create(username=username)
  9. for tweet in tweets:
  10. Tweet.create(user=user, content=tweet)
  11. # Populate a few favorites for our users, such that:
  12. favorite_data = (
  13. ('huey', ['whine']),
  14. ('mickey', ['purr']),
  15. ('zaizee', ['meow', 'purr']))
  16. for username, favorites in favorite_data:
  17. user = User.get(User.username == username)
  18. for content in favorites:
  19. tweet = Tweet.get(Tweet.content == content)
  20. Favorite.create(user=user, tweet=tweet)

This gives us the following:

UserTweetFavorited by
hueymeowzaizee
hueyhiss 
hueypurrmickey, zaizee
mickeywoof 
mickeywhinehuey

Attention

In the following examples we will be executing a number of queries. If you are unsure how many queries are being executed, you can add the following code, which will log all queries to the console:

  1. import logging
  2. logger = logging.getLogger('peewee')
  3. logger.addHandler(logging.StreamHandler())
  4. logger.setLevel(logging.DEBUG)

Note

In SQLite, foreign keys are not enabled by default. Most things, including the Peewee foreign-key API, will work fine, but ON DELETE behaviour will be ignored, even if you explicitly specify on_delete in your ForeignKeyField. In conjunction with the default AutoField behaviour (where deleted record IDs can be reused), this can lead to subtle bugs. To avoid problems, I recommend that you enable foreign-key constraints when using SQLite, by setting pragmas={'foreign_keys': 1} when you instantiate SqliteDatabase.

  1. # Ensure foreign-key constraints are enforced.
  2. db = SqliteDatabase('my_app.db', pragmas={'foreign_keys': 1})