Skip to main content

a little orm

Project description

https://media.charlesleifer.com/blog/photos/peewee4-logo.png

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)

  • tons of extensions

  • use with flask, fastapi, pydantic, and more.

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?

https://media.charlesleifer.com/blog/photos/wat.jpg

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:

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

peewee-4.2.0.tar.gz (777.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

peewee-4.2.0-py3-none-any.whl (172.7 kB view details)

Uploaded Python 3

File details

Details for the file peewee-4.2.0.tar.gz.

File metadata

  • Download URL: peewee-4.2.0.tar.gz
  • Upload date:
  • Size: 777.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for peewee-4.2.0.tar.gz
Algorithm Hash digest
SHA256 f722deabea8259f82bdb454f3a97c07896dc4b37b87ec1ab9ee4b1d4ac34e8d9
MD5 c8757b2ab1c284ad377188a2e75949b1
BLAKE2b-256 187af6e7f33816faa526a7ebdcbbc88f6a48f4c10062a2a8c48b3ec9d397f8ad

See more details on using hashes here.

File details

Details for the file peewee-4.2.0-py3-none-any.whl.

File metadata

  • Download URL: peewee-4.2.0-py3-none-any.whl
  • Upload date:
  • Size: 172.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for peewee-4.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9be956f82a92e7d737ead83800f1041d68fb62c5cbc342cca65c9aad900062e6
MD5 f695afabd2dff4817f57274b9450b11e
BLAKE2b-256 7a6742909ad5bbae4e9c74edfd69962b9b6a39d76798664918860db11d70d975

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page