Peewee ORM
Peewee is a simple and small Python ORM (Object-Relational Mapper) that provides an expressive interface for database operations. It supports SQLite, MySQL/MariaDB, and PostgreSQL, and offers flexible query-building, asyncio support, and numerous extensions. The library is actively maintained with frequent releases, currently at version 4.0.3.
Warnings
- breaking Peewee 4.0.2 removed all Python 2.x compatibility code. Projects still on Python 2 must use an older Peewee version (<=3.x).
- breaking In `playhouse.dataset` (Peewee 4.0.2), the default binary data serialization changed from base64 to hex. If you rely on base64 encoding for existing data, you must explicitly specify `base64_bytes=True` during deserialization.
- breaking `SqliteExtDatabase` was removed in Peewee 4.0.1 as it served no significant purpose in Peewee 4.0. Use `SqliteDatabase` instead.
- breaking As of Peewee 3.19.0, SQLite C extensions are no longer built and shipped by default. If you require these extensions (e.g., for FTS5 ranking functions or fuzzy string matching), you need to install Peewee from the sdist.
- breaking In Peewee 3.18.0, the behavior of `postgresql_ext.BinaryJSONField.contains()` changed. It now *always* uses the JSONB contains operator (`@>`). Previously, passing a string would perform a JSON key existence check (`?`).
- gotcha Peewee uses bitwise operators (`&` for AND, `|` for OR) for logical operations in queries, not Python's `and`/`or` keywords, because Python coerces logical operations to boolean values. Similarly, for 'IN' queries, use the `.in_()` method instead of the Python `in` operator.
- breaking Peewee 3.16.0 changed how it initializes connections to DB-API drivers. It now places the driver in autocommit mode directly, instead of emulating autocommit. If you directly use `Database.connection()` or `Database.cursor()`, your queries will now execute in autocommit mode.
Install
-
pip install peewee -
pip install peewee[mysql] -
pip install peewee[postgres] -
pip install peewee[psycopg3] -
pip install peewee --no-binary :all:
Imports
- Model
from peewee import Model
- SqliteDatabase
from peewee import SqliteDatabase
- PostgresqlDatabase
from peewee import PostgresqlDatabase
- MySQLDatabase
from peewee import MySQLDatabase
- CharField
from peewee import CharField
- TextField
from peewee import TextField
- ForeignKeyField
from peewee import ForeignKeyField
- DateTimeField
from peewee import DateTimeField
Quickstart
import datetime
from peewee import *
db = SqliteDatabase(':memory:') # Use an in-memory SQLite database
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
username = CharField(unique=True)
class Tweet(BaseModel):
user = ForeignKeyField(User, backref='tweets')
content = TextField()
timestamp = DateTimeField(default=datetime.datetime.now)
def run_quickstart():
db.connect()
db.create_tables([User, Tweet])
# Create users
charlie = User.create(username='charlie')
huey = User.create(username='huey')
# Create tweets
Tweet.create(user=charlie, content='Hello from Charlie!')
Tweet.create(user=huey, content='Meow!')
Tweet.create(user=charlie, content='Another tweet.')
# Query data
print("\n--- All Tweets ---")
for tweet in Tweet.select().order_by(Tweet.timestamp.desc()):
print(f"{tweet.user.username} -> {tweet.content}")
# Get a single user's tweets
print("\n--- Charlie's Tweets ---")
for tweet in charlie.tweets:
print(f"{tweet.user.username} -> {tweet.content}")
db.close()
if __name__ == '__main__':
run_quickstart()