其实peewee实现的这个ORM没有什么特殊的,和其他的ORM在查询表现上差不多。如果我们已经用过其他的ORM就会发现peewee很易于掌握。
table.select(),这就是select * from 。。。。
举个例子。查询用户的is_staff=Tree,他的blog是LIVE状态的记录。
>>> Blog.select().where(status=LIVE).join(User).where(is_staff=True)
注意:这里
join() 两个model,必须是用 ForeignKeyField 连接的.
还有另外一招
>>> Blog.select().where(
... status=LIVE,
... user__in=User.select().where(is_staff=True)
... )
而这种没有直接明确的使用JOIN,他用的是where这个子查询
# using subqueries
SELECT * FROM blog
WHERE (
status = ? AND
user_id IN (
SELECT t1.id FROM user AS t1 WHERE t1.is_staff = ?
)
)
如果用了JOIN,
# using joins
SELECT t1.* FROM blog AS t1
INNER JOIN user AS t2
ON t1.user_id = t2.id
WHERE
t1.status = ? AND
t2.is_staff = ?
django中
假如你希望返回blog的记录并且还要附上他在Entry上的记录数。
query = Blog.select().annotate(Entry)
这相当于
query = Blog.select({
Blog: ['*'],
Entry: [Count('id')],
}).group_by(Blog).join(Entry)
这样在就除了blog的全部字段信息会返回之外,还加上了在Entry上count的。这两个model在FK非空时连接默认是inner join,也就是如果某个blog没有entries就不会出现在返回记录中了。作为补救,我们要显示设置join的类型。
query = Blog.select().join(Entry, 'left outer').annotate(Entry)
You can also specify a custom aggregator:
query = Blog.select().annotate(Entry, peewee.Max('pub_date', 'max_pub_date'))
但是如果你仅仅想展示一个纯属字信息,比如count,MAX等,那就用 aggregate() 方法:
max_id = Blog.select().aggregate(Max('id'))
R是RawQuery的简写。
动态查询
a_users = query.where(R('first_letter=%s', 'a'))
每个操作生效之前都必须调用execute方法,返回值是数据库受影响的行数。其中query操作虽然表面上可以不调用execute但实际上这个是在后台被调用了,返回的是QueryResultWrapper。
>>> dq = User.delete().where(active=False) # <-- returns a DeleteQuery
>>> dq
>>> dq.execute() # <-- executes the query and returns number of rows deleted
3
>>> uq = User.update(active=True).where(id__gt=3) # <-- returns an UpdateQuery
>>> uq
>>> uq.execute() # <-- executes the query and returns number of rows updated
2
>>> iq = User.insert(username='new user') # <-- returns an InsertQuery
>>> iq
>>> iq.execute() # <-- executes query and returns the new row's PK
3
>>> sq = User.select().where(active=True) # <-- returns a SelectQuery
>>> sq
>>> qr = sq.execute() # <-- executes query and returns a QueryResultWrapper
>>> qr
>>> [u.id for u in qr]
[1, 2, 3, 4, 7, 8]
>>> [u.id for u in qr] # <-- re-iterating over qr does not re-execute query
[1, 2, 3, 4, 7, 8]
>>> [u.id for u in sq] # <-- as a shortcut, you can iterate directly over
>>> # a SelectQuery (which uses a QueryResultWrapper
>>> # behind-the-scenes)
[1, 2, 3, 4, 7, 8]
class SelectQuery
Return type: | SelectQuery |
---|
indicates that this query should only attempt to reconstruct a single modelinstance for every row returned by the cursor. if multiple tables were queried,the columns returned are patched directly onto the single model instance.
Note
在一个很大的结果集上使用naive,能十分高效的迭代。
# above example
entries = Entry.select({
Entry: ['*'],
Blog: ['*'],
}).order_by(('pub_date', 'desc')).join(Blog)
for entry in entries.limit(10):
print '%s, posted on %s' % (entry.title, entry.blog.title)#注意:entry.blog.title。这里entry通过外键取得blog再访问title
也可以
# very similar query to the above -- main difference is we're
# aliasing the blog title to "blog_title"
entries = Entry.select({
Entry: ['*'],
Blog: [('title', 'blog_title')],
}).order_by(('pub_date', 'desc')).join(Blog)
entries = entries.naive()
# now instead of calling "entry.blog.title" the blog's title
# is exposed directly on the entry model as "blog_title" and
# no blog instance is created
for entry in entries.limit(10):
print '%s, posted on %s' % (entry.title, entry.blog_title)#看到不同之处了吧。title就好像是entry自己的一个字段一样了。entry.blog_title
文档中还提到了switch方法,我感觉比较鸡肋。不值得一学。
count() 不解释
Return type: | 用来查询某个特定的记录是否存在。 |
---|
>>> sq = User.select().where(active=True)
>>> if sq.where(username=username, password=password).exists():
... authenticated = True
having()继续不解释
order_by()看这个例子就知道了
>>> sq = Entry.select().join(Blog).order_by(
... (Blog, 'title'), # order by blog title ascending
... (Entry, 'pub_date', 'DESC'), # then order by entry pub date desc
... )
Parameters: |
|
---|---|
Return type: | SelectQuery |
形式类似与limit()、offset()
>>> Blog.select().order_by('username').paginate(3, 20) # <-- get blogs 41-60