Peewee 2.0 -- a complete rewrite

100 views
Skip to first unread message

Charles

unread,
Oct 2, 2012, 1:42:10 PM10/2/12
to peewe...@googlegroups.com
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.

You can see the new code on github in the "unstable/2.0" branch: https://github.com/coleifer/peewee/tree/unstable/2.0

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)

Charles

unread,
Oct 2, 2012, 1:42:53 PM10/2/12
to peewe...@googlegroups.com
Forgot to mention, but as much as possible, I will try and preserve compatibility with the existing APIs!

方雷

unread,
Oct 5, 2012, 4:59:29 AM10/5/12
to peewe...@googlegroups.com
Cool, I like it.

Jun Liu

unread,
Oct 26, 2012, 2:16:58 AM10/26/12
to peewe...@googlegroups.com
How about composite primary key support?

Ivan Kleshnin

unread,
Nov 6, 2012, 2:47:03 PM11/6/12
to peewe...@googlegroups.com
I'd propose to tweak some naming convention
We know that

class Model:
    pass

is equal to

Model = type('Model', ...)

So variables which contain classes should be named in CamelCase.

In this way you can replace ugly

def something(self, model_class)
    model = model_class
    # 100 lines after it's hard to say what kind of object `model` is: class or instance

with 

def something(self, Model):   
    # Model is obviosly a class and not an instance!

Indra Gunawan

unread,
Nov 15, 2012, 9:11:55 PM11/15/12
to peewe...@googlegroups.com
Hi Charles, when the 2.0 version become master branch?
Are the 2.0 version now ready for production?

Thanks
--
Salam
Indra Gunawan

Charles

unread,
Nov 16, 2012, 1:07:27 PM11/16/12
to peewe...@googlegroups.com

Indra Gunawan

unread,
Nov 17, 2012, 5:48:43 PM11/17/12
to peewe...@googlegroups.com
I really like this 2.0 version, this is exactly Python way, not Ruby way
Please make it a master branch if you don't mind Charles :)

Congrats!
--
Regards
Indra Gunawan

Charles Leifer

unread,
Nov 17, 2012, 11:30:44 PM11/17/12
to peewe...@googlegroups.com
I merged it in to master a while back.  That commit is the merge.
Reply all
Reply to author
Forward
0 new messages