Model definitions
We’ll use the following model definitions for our examples:
- import datetime
- from peewee import *
- db = SqliteDatabase(':memory:')
- class BaseModel(Model):
- class Meta:
- database = db
- class User(BaseModel):
- username = TextField()
- class Tweet(BaseModel):
- content = TextField()
- timestamp = DateTimeField(default=datetime.datetime.now)
- user = ForeignKeyField(User, backref='tweets')
- class Favorite(BaseModel):
- user = ForeignKeyField(User, backref='favorites')
- tweet = ForeignKeyField(Tweet, backref='favorites')
Peewee uses ForeignKeyField
to define foreign-key relationshipsbetween models. Every foreign-key field has an implied back-reference, which isexposed as a pre-filtered Select
query using the providedbackref
attribute.
Creating test data
To follow along with the examples, let’s populate this database with some testdata:
- def populate_test_data():
- db.create_tables([User, Tweet, Favorite])
- data = (
- ('huey', ('meow', 'hiss', 'purr')),
- ('mickey', ('woof', 'whine')),
- ('zaizee', ()))
- for username, tweets in data:
- user = User.create(username=username)
- for tweet in tweets:
- Tweet.create(user=user, content=tweet)
- # Populate a few favorites for our users, such that:
- favorite_data = (
- ('huey', ['whine']),
- ('mickey', ['purr']),
- ('zaizee', ['meow', 'purr']))
- for username, favorites in favorite_data:
- user = User.get(User.username == username)
- for content in favorites:
- tweet = Tweet.get(Tweet.content == content)
- Favorite.create(user=user, tweet=tweet)
This gives us the following:
User | Tweet | Favorited by |
---|---|---|
huey | meow | zaizee |
huey | hiss | |
huey | purr | mickey, zaizee |
mickey | woof | |
mickey | whine | huey |
Attention
In the following examples we will be executing a number of queries. If youare unsure how many queries are being executed, you can add the followingcode, which will log all queries to the console:
- import logging
- logger = logging.getLogger('peewee')
- logger.addHandler(logging.StreamHandler())
- logger.setLevel(logging.DEBUG)
Note
In SQLite, foreign keys are not enabled by default. Most things, includingthe Peewee foreign-key API, will work fine, but ON DELETE behaviour will beignored, even if you explicitly specify on_delete
in yourForeignKeyField
. In conjunction with the defaultAutoField
behaviour (where deleted record IDs can be reused),this can lead to subtle bugs. To avoid problems, I recommend that youenable foreign-key constraints when using SQLite, by settingpragmas={'foreign_keys': 1}
when you instantiate SqliteDatabase
.
- # Ensure foreign-key constraints are enforced.
- db = SqliteDatabase('my_app.db', pragmas={'foreign_keys': 1})