peewee 一个轻量级的ORM (三)


现在该讲讲怎么用peewee查询了

其实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 = ?

查询的时候用到的一些运算符。

==:
x = y
<:
x < y
<=:
x <= y
>:
x > y
>=:
x >= y
!=:
x != y
*:
检查是否包含字串(大小写敏感)
**:
不敏感的检查是否包含字串
^:
大小写不敏感的检查字符串前缀
>>:
x IS (NOT) NULL, depending on if y is True or False
<<:
相当于IN,这里y是一个list或者 SelectQuery

django中

__between:
也就是between,这里y是一个tuple或者list

汇总记录

假如你希望返回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'))

SQL Functions, “Raw expressions” and the R() object采用原始结构来查询

R是RawQuery的简写。

动态查询

a_users = query.where(R('first_letter=%s', 'a'))

execute()

每个操作生效之前都必须调用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

     naive ( )
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()   不解释

exists ( )
Return type: 用来查询某个特定的记录是否存在。
>>> sq = User.select().where(active=True)
>>> if sq.where(username=username, password=password).exists():
...     authenticated = True
group_by() 不解释

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
... )

paginate ( page_num, paginate_by=20 )
Parameters:
  • page_num –页码
  • paginate_by –每页多少条记录
Return type:

SelectQuery

形式类似与limit()、offset()

>>> Blog.select().order_by('username').paginate(3, 20) # <-- get blogs 41-60

distinct ( )不解释

你可能感兴趣的:(python,mysql)