本文将简单的介绍Peewee,一览它的主要特点,主要涉及到:

  • 模型定义
  • 存储数据
  • 检索数据

注意:如果你偏爱稍微高级一点的教程, peewee建立类似twitter应用 是一篇结合Flask框架与peewee的全面教程。

强烈 建议通过SHELL交互的方式执行命令,这种方式可以提高你输入查询的快感。

模型定义

模型类、字段以及模型实例与数据的对于关系:

peewee 数据库
Model class Database table
Field instance Column on a table
Model instance Row in a database table

开始一个peewee的项目时,通常最好通过定义一个或多个 Model classes: 来开始你的数据模型。

from peewee import *

db = SqliteDatabase('people.db')

class Person(Model):
name = CharField()
birthday = DateField()
is_relative = BooleanField() class Meta:
database = db # This model uses the "people.db" database.

Note

注意我们使用 Person 替代了 People 来命名我们的模型,你应该遵循这个约定——即使该表包含多个人,我们总是使用单数的形式来命名模型类。

有许多 field types 适用于存储各种类型的数据,Peewee可以自动的转换python中的值到数据库中使用,所以你不用担心代码中Python的类型。

当我们通过使用 外键 来创建关联模型的时候非常有趣,使用peewee将变得非常简单:

class Pet(Model):
owner = ForeignKeyField(Person, related_name='pets')
name = CharField()
animal_type = CharField() class Meta:
database = db # this model uses the "people.db" database

现在我们有了模型,接下来连接数据库吧,虽然没有必要建立显示连接,这是个好的习惯,一旦发现连接数据发送错误,便可以排除之后的查询错误,当处理完毕后应当关闭连接。比如:一个web应用程序当收到请求的时候可能会打开一个连接,响应后将关闭连接。

>>> db.connect()

然后我们在数据库中传接用于存储我们数据的表,这将创建具有相应列、索引、自增键以及外键:

>>> db.create_tables([Person, Pet])

存储数据

接下来我们用一些人填充数据库吧,可以使用 save() 与 create() 方法添加和更新人的记录。

>>> from datetime import date
>>> uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15), is_relative=True)
>>> uncle_bob.save() # bob is now stored in the database
1

Note

当你调用 save() 的时候,将返回影响到的行数。

你也可以调用 create() 方法新增一个人,它将返回一个模型实例:

>>> grandma = Person.create(name='Grandma', birthday=date(1935, 3, 1), is_relative=True)
>>> herb = Person.create(name='Herb', birthday=date(1950, 5, 5), is_relative=False)

为了更新一行,可以修改模型实例,调用 save() 来保存更改。这里我们将改变Grandma名字,然后存储到数据库:

>>> grandma.name = 'Grandma L.'
>>> grandma.save() # Update grandma's name in the database.
1

现在我们已经在数据库中保存了3个人了,接下来给他们一些宠物吧。Grandma不喜欢宠物在屋子里乱跑,所以她一只都没有,但Herb是个宠物达人:

>>> bob_kitty = Pet.create(owner=uncle_bob, name='Kitty', animal_type='cat')
>>> herb_fido = Pet.create(owner=herb, name='Fido', animal_type='dog')
>>> herb_mittens = Pet.create(owner=herb, name='Mittens', animal_type='cat')
>>> herb_mittens_jr = Pet.create(owner=herb, name='Mittens Jr', animal_type='cat')

在经历很长的一段生活后,Mittens生病死了,我们需要将它从数据库中移出:

>>> herb_mittens.delete_instance() # he had a great life
1

Note

delete_instance() 返回所有影响到的删除行数。

Bob叔叔考虑到Herb家已经死了许多宠物,决定收养Fido:

>>> herb_fido.owner = uncle_bob
>>> herb_fido.save()
>>> bob_fido = herb_fido # rename our variable for clarity

检索数据

数据库的强大之处在于允许我们通过 查询 来检索数据,关系型数据库针对点对点查询非常优异。

获取单条数据

让我们从数据库中获取Grandma的数据,使用 SelectQuery.get() 来从数据库中获取单条数据:

>>> grandma = Person.select().where(Person.name == 'Grandma L.').get()

我们也可以等价简写成 Model.get() :

>>> grandma = Person.get(Person.name == 'Grandma L.')

记录列表

获取数据库中的所有人:

>>> for person in Person.select():
... print person.name, person.is_relative
...
Bob True
Grandma L. True
Herb False

获取数据库中所有猫以及主人的名字:

>>> query = Pet.select().where(Pet.animal_type == 'cat')
>>> for pet in query:
... print pet.name, pet.owner.name
...
Kitty Bob
Mittens Jr Herb

上一个查询是有问题的:因为我们访问了 pet.owner.name ,但我们并没有在原始查询中进行查询,peewee不得不进行一个额外的查询来检索宠物的主人,该行为请参考 N+1 ,通常这应当避免的。

为了避免额外的查询,我们可以通过添加 join 来同时查询 Pet 和 Person

>>> query = (Pet
... .select(Pet, Person)
... .join(Person)
... .where(Pet.animal_type == 'cat'))
>>> for pet in query:
... print pet.name, pet.owner.name
...
Kitty Bob
Mittens Jr Herb

获取Bob的所有宠物

>>> for pet in Pet.select().join(Person).where(Person.name == 'Bob'):
... print pet.name
...
Kitty
Fido

我们还可以做另外一件很酷的事情来获取Bob的宠物,一旦拥有可以代表Bob的对象,我们可以这样替代:

>>> for pet in Pet.select().where(Pet.owner == uncle_bob):
... print pet.name

可以通过 order_by() 语句来排序:

>>> for pet in Pet.select().where(Pet.owner == uncle_bob).order_by(Pet.name):
... print pet.name
...
Fido
Kitty

获取有所人,并且按照年龄从小到大排序:

>>> for person in Person.select().order_by(Person.birthday.desc()):
... print person.name, person.birthday
...
Bob 1960-01-15
Herb 1950-05-05
Grandma L. 1935-03-01

获取所有人 以及 他们宠物的一些信息:

>>> for person in Person.select():
... print person.name, person.pets.count(), 'pets'
... for pet in person.pets:
... print ' ', pet.name, pet.animal_type
...
Bob 2 pets
Kitty cat
Fido dog
Grandma L. 0 pets
Herb 1 pets
Mittens Jr cat

我们再一次运行了典型的 N+1 查询行为,可以进行 JOIN 操作并且合并起来:

>>> subquery = Pet.select(fn.COUNT(Pet.id)).where(Pet.owner == Person.id)
>>> query = (Person
... .select(Person, Pet, subquery.alias('pet_count'))
... .join(Pet, JOIN.LEFT_OUTER)
... .order_by(Person.name)) >>> for person in query.aggregate_rows(): # Note the `aggregate_rows()` call.
... print person.name, person.pet_count, 'pets'
... for pet in person.pets:
... print ' ', pet.name, pet.animal_type
...
Bob 2 pets
Kitty cat
Fido dog
Grandma L. 0 pets
Herb 1 pets
Mittens Jr cat

甚至我们创建了单独的子查询,但只执行了 有且仅有一个 查询。

最后我们处理一个复杂一点的,获取所有人,只要他们的生日:

  • 1940之前 (grandma)
  • 1959之后 (bob)
>>> d1940 = date(1940, 1, 1)
>>> d1960 = date(1960, 1, 1)
>>> query = (Person
... .select()
... .where((Person.birthday < d1940) | (Person.birthday > d1960)))
...
>>> for person in query:
... print person.name, person.birthday
...
Bob 1960-01-15
Grandma L. 1935-03-01

现在在做一件相反的事情,获取1940到1960之间的人:

>>> query = (Person
... .select()
... .where((Person.birthday > d1940) & (Person.birthday < d1960)))
...
>>> for person in query:
... print person.name, person.birthday
...
Herb 1950-05-05

最后一次查询,使用SQL函数来检索所有名字以 G 开头的人,不区分大小写:

>>> expression = (fn.Lower(fn.Substr(Person.name, 1, 1)) == 'g')
>>> for person in Person.select().where(expression):
... print person.name
...
Grandma L.

我们已经处理完数据库,最后关闭连接:

>>> db.close()

这些都是基础的使用,你可以进行更加复杂的操作。

所有其他的一些SQL语句也是可用的,比如:

  • group_by()
  • having()
  • limit() 与 offset()

详情请参考 Querying 文档。

与现有的数据库一起工作

如果你已经拥有了数据库,可以使用 pwiz, a model generator 模型生成器自动生成peewee模型,例如,如果我有一个名为 charles_blog 的postgresql数据库,我可能会运行:

python -m pwiz -e postgresql charles_blog > blog_models.py

peewee基本操作的更多相关文章

  1. [Python]peewee使用经验

    peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...

  2. [Python]peewee 使用经验

    peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...

  3. python轻量级orm框架 peewee常用功能速查

    peewee常用功能速查 peewee 简介 Peewee是一种简单而小的ORM.它有很少的(但富有表现力的)概念,使它易于学习和直观的使用. 常见orm数据库框架 Django ORM peewee ...

  4. Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作

    一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. 三、Redis基本操作——List

    小喵的唠叨话:前面我们介绍了Redis的string的数据结构的原理和操作.当时我们提到Redis的键值对不仅仅是字符串.而这次我们就要介绍Redis的第二个数据结构了,List(链表).由于List ...

  8. 二、Redis基本操作——String(实战篇)

    小喵万万没想到,上一篇博客,居然已经被阅读600次了!!!让小喵感觉压力颇大.万一有写错的地方,岂不是会误导很多筒子们.所以,恳请大家,如果看到小喵的博客有什么不对的地方,请尽快指正!谢谢! 小喵的唠 ...

  9. 一、Redis基本操作——String(原理篇)

    小喵的唠叨话:最近京东图书大减价,小喵手痒了就买了本<Redis设计与实现>[1]来看看.这里权当小喵看书的笔记啦.这一系列的模式,主要是先介绍Redis的实现原理(可能很大一部分会直接照 ...

随机推荐

  1. 解决java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList的问题

    一.背景 最近闲来无事,想自己搭建一套Spring+SpringMVC+Mybatis+Mysql的环境(搭建步骤会在以后博客中给出),结果运行程序时,适用@ResponseBody注解进行返回Lis ...

  2. Linux常用命令英文全称与中文解释

    man: Manual 意思是手册,可以用这个命令查询其他命令的用法. pwd:Print working directory 意思是密码. su:Swith user 切换用户,切换到root用户 ...

  3. JavaWeb 并发:FOR UPDATE 实战,监测并解决。

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 一.前言 针对并发,老生常谈了.目前一个通用的做法有两种:锁机制:1.悲观锁:2.乐观锁. 但是这篇我 ...

  4. 动车上的书摘-java网络 连接服务器

    摘要: 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 应该有些延迟,你会看到黑幕中弹出 来自USA的X原子的计量时间: ...

  5. Web Service 部分内容简述(2)

    1. CORBA是什么?用途是什么?  CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture),由对象管理组织 (Object M ...

  6. Linux终端会话实时共享(kibitz)

    另一篇关于终端会话共享的文章:Linux录制.回放和共享终端操作 kibitz可以将一个会话(你所操作的)实时分享给本机的其它登陆用户(你想让别人看到的).通过这个工具,你敲什么命令,输出了什么内容对 ...

  7. python下载安装BeautifulSoup库

    python下载安装BeautifulSoup库 1.下载https://www.crummy.com/software/BeautifulSoup/bs4/download/4.5/ 2.解压到解压 ...

  8. [JavaScript] XMLHttpRequest记录

    XMLHttpRequest 使用 XMLHttpRequest 对象可以和服务器进行交互,可以获取到数据,而无需让整个页面进行刷新.这样 web 页面可以做到只更新局部页面,降低了对用户操作的影响. ...

  9. 在Fragment中保存WebView状态

    http://www.lucazanini.eu/2013/android/how-to-save-the-state-of-a-webview-inside-a-fragment-of-an-act ...

  10. WPF里ItemsControl的分组实现 --listbox 实现分组

    我们在用到ItemsControl时,有时会用到分组,如ListBox,ListView,DataGrid.WPF的ItemsControl可以实现分组,是依托于GroupStyle,以ListBox ...