peewee
Peewee is a simple and small ORM. It has few (but expressive) concepts, making it easy to learn and intuitive to use.
Peewee is a single module with no required dependencies and has been running production workloads of all sizes since 2010.
a small, expressive ORM
flexible query-builder that exposes full power of SQL
supports sqlite, mysql, mariadb, postgresql
asyncio support built on the standard async drivers (aiosqlite, asyncpg, aiomysql)
schema migrations with diff-based generation (pwmigrate)
tons of extensions
New to peewee? These may help:
Installation:
pip install peewee
Sqlite comes built-in provided by the standard-lib sqlite3 module. Other backends can be installed using the following instead:
pip install peewee[mysql] # Install peewee with pymysql.
pip install peewee[postgres] # Install peewee with psycopg2.
pip install peewee[psycopg3] # Install peewee with psycopg3.
# AsyncIO implementations.
pip install peewee[aiosqlite] # Install peewee with aiosqlite.
pip install peewee[aiomysql] # Install peewee with aiomysql.
pip install peewee[asyncpg] # Install peewee with asyncpg.
Examples
Defining models is similar to Django or SQLAlchemy:
from peewee import *
import datetime
db = SqliteDatabase('my_database.db')
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
username = CharField(unique=True)
class Tweet(BaseModel):
user = ForeignKeyField(User, backref='tweets')
message = TextField()
created_date = DateTimeField(default=datetime.datetime.now)
is_published = BooleanField(default=True)
Connect to the database and create tables:
db.connect()
db.create_tables([User, Tweet])
Create a few rows:
charlie = User.create(username='charlie')
huey = User(username='huey')
huey.save()
# No need to set `is_published` or `created_date` since they
# will just use the default values we specified.
Tweet.create(user=charlie, message='My first tweet')
Queries are expressive and composable:
# A simple query selecting a user.
User.get(User.username == 'charlie')
# Get tweets created by one of several users.
usernames = ['charlie', 'huey', 'mickey']
users = User.select().where(User.username.in_(usernames))
tweets = Tweet.select().where(Tweet.user.in_(users))
# We could accomplish the same using a JOIN:
tweets = (Tweet
.select()
.join(User)
.where(User.username.in_(usernames)))
# How many tweets were published today?
tweets_today = (Tweet
.select()
.where(
(Tweet.created_date >= datetime.date.today()) &
(Tweet.is_published == True))
.count())
# Paginate the user table and show me page 3 (users 41-60).
User.select().order_by(User.username).paginate(3, 20)
# Order users by the number of tweets they've created:
tweet_ct = fn.Count(Tweet.id)
users = (User
.select(User, tweet_ct.alias('ct'))
.join(Tweet, JOIN.LEFT_OUTER)
.group_by(User)
.order_by(tweet_ct.desc()))
# Do an atomic update (for illustrative purposes only, imagine a simple
# table for tracking a "count" associated with each URL). We don't want to
# naively get the save in two separate steps since this is prone to race
# conditions.
Counter.update(count=Counter.count + 1).where(Counter.url == request.url).execute()
Check out the example twitter app.
Asyncio
import asyncio
from peewee import *
from playhouse.pwasyncio import AsyncPostgresqlDatabase
db = AsyncPostgresqlDatabase('my_app')
class User(db.Model):
username = CharField(unique=True)
class Tweet(db.Model):
user = ForeignKeyField(User, backref='tweets')
message = TextField()
async def main():
async with db:
await db.acreate_tables([User, Tweet])
# Queries are awaited on the event loop using asyncpg.
huey = await User.acreate(username='huey')
tweet = await Tweet.acreate(user=huey, message='meow')
async with db.atomic():
tweet.message = 'purr'
await tweet.asave()
# Create a query - nothing is executed yet.
query = Tweet.select(Tweet, User).join(User)
# Execute and buffer the results.
tweets = await query.aexecute() # Or: await db.list(query)
for tweet in tweets:
print(tweet.user.username, '->', tweet.message)
# Streaming results via server-side cursor.
async for tweet in db.iterate(query):
print(tweet.user.username, '->', tweet.message)
await db.close_pool()
asyncio.run(main())
See the asyncio docs for details.
Learning more
Check the documentation for more examples.
Specific question? Come hang out in the #peewee channel on irc.libera.chat, or post to the mailing list, http://groups.google.com/group/peewee-orm . If you would like to report a bug, create a new issue on GitHub.
Still want more info?
I’ve written a number of blog posts about building applications and web-services with peewee (and usually Flask). If you’d like to see some real-life applications that use peewee, the following resources may be useful:
Release files for peewee 4.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| peewee-4.5.1.tar.gz | 823.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| peewee-4.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.0 MB
Release files / peewee-4.5.1.tar.gz
| Download URL | peewee-4.5.1.tar.gz |
|---|---|
| Size | 823.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8005cb45c54e1a282a2f24ddd583f0f7a80cd5d9c635d50d63f57c11d88c392a
|
|
BLAKE2b-256 checksum How to use checksums |
ed9b74f549937d7edfb75742f426347a7483b0aab70909e2250e44f067027094
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / peewee-4.5.1-py3-none-any.whl
| Download URL | peewee-4.5.1-py3-none-any.whl |
|---|---|
| Size | 193.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dbbdc93e9be08d1df49ceed48dc5d609bfeda6112848086f1f6c1f1debe70975
|
|
BLAKE2b-256 checksum How to use checksums |
13903ddf6ef69090c63b6fe0d42b41e5dd3323d95dfe01eda6766305337be862
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|