Hi everyone,
For some time I've been planning a rewrite to resolve some of the "big" problems I see with peewee's current (1.0) implementation.
The rewrite aims to resolve the following issues:
- inconsistency in handling select, order by, group by clauses
- inconsistency in handling where and having clauses
- special-casing which led me to hack in "F" and "R" objects
- lack of flexibility in handling query parsing and sql generation
- the tests module...omg
- extra layers of abstraction to make up for API deficiencies i.e. database/adapter and field/column
The rewrite introduces an entirely new sql compiler that I think is going to be really nice going forward. It also simplifies and unifies querying APIs.
Here are the examples from the readme. I will show the "old" and the "new":
class User(Model):
username = CharField()
is_staff = BooleanField()
is_superuser = BooleanField()
class Tweet(Model):
user = ForeignKeyField(User, related_name='tweets')
content = CharField(max_length=255)
timestamp = DateTimeField(default=datetime.datetime.now)
User.get(username='charles')
User.get(User.username == 'charles')
# get the staff and super users
editors = User.select().where(Q(is_staff=True) | Q(is_superuser=True))
editors = User.select().where((User.is_staff == True) | (User.is_superuser == True))
# get tweets by editors
Tweet.select().where(user__in=editors)
Tweet.select().where(Tweet.user << editors)
# how many active users are there?
User.select().where(active=True).count()
User.select().where(User.active == True).count()
# paginate the user table and show me page 3 (users 41-60)
User.select().order_by(('username', 'asc')).paginate(3, 20)
User.select().order_by(User.username.asc()).paginate(3, 20)
# order users by number of tweets
User.select().annotate(Tweet).order_by(('count', 'desc'))
User.select(
User, fn.Count(Tweet.id).set_alias('count')
).join(Tweet).order_by(fn.Count(Tweet.id).desc())
# do an atomic update
Employee.update(salary=F('salary') + 1000)
Employee.update(salary=Employee.salary + 1000)
# users where their username is their firstname
User.select().where(username=F('first_name'))
User.select().where(User.username == User.first_name)
# here are some fun new things you can do:
# users whose username startswith 'a'
User.select().where(fn.Lower(fn.Substr(User.username, 0, 1)) == 'a')
# compare one column against another in the where clause
User.select().where(User.username == User.first_name)
# rich having clause
User.select(User, fn.Count(Tweet.id).set_alias('count')).join(Tweet).having(fn.Count(Tweet.id) > 10)