peewee入门

来源:互联网 发布:ubuntu安装maven 编辑:程序博客网 时间:2024/05/29 12:30

peewee quick start

摘要

peewee是python ORM的一个框架。

安装

  • 使用pip直接安装最新版本
pip install peewee
  • 使用git安装

项目的地址: https://github.com/coleifer/peewee

git clone https://github.com/coleifer/peeweecd peeweepython setup.py install

快速开始

本编文档为peewee主要功能做了一个简明的、高水准的概述,目录包含:
- 模块定义
- 存储数据
- 检索数据

模块定义

Model classes, fields and model instances 都映射了数据库的概念:

Thing Corresponds to database Modelclasses db table fields table column model instance Row in table

当使用peewee开始一个项目时,一贯最好的方式就是从数据模型开始,通过定义一个或多个模型类

from peewee import *db = SqliteDatabase('people.db')clss Person(Model):    name = CharFiled()    birthday = DateFiled()    is_relative = BooleanFiled()    class Meta:        database = db

这里提供了很多类型的field,以便适合存储不同类型的数据。peewee处理器可以将python里的数值类型转换为数据库中的数据类型,因此,您可以在代码中使用Python类型,而不必担心

当我们用外键给model之间建立起联系后,事情就开始变得有趣了。
在peewee中可以轻松是实现:

class Pets(Model):    owner = ForeignKeyField(Person,related_name='pets')    name = CharField()    animal_type = CharField()    class Meta:        database = db

既然我们有自己的model,那就让它们和数据库关联起来吧。虽然没有必要显式地打开连接,这是一个很好的做法,因为它会立即显示您的数据库连接的任何错误,与第一次查询执行后的任意时间不同。完成后关闭连接也是很好的–例如,一个web app当接收一个请求时要打开数据库连接,响应时要关闭连接。

db.connect()

首先,我们将在数据库中创建存储数据的表。这将创建具有适当列、索引、序列和外键约束的表。

db.create_tables([People,pets])

数据存储

首先,我们用一些people对象填充数据库吧。可以使用save()和create()方法添加和更新people记录

from datetime import dateuncle_bob = Person(name='Bob',birthday=date(1960,1,15),is_relative = True)uncle_bob.save()

调用save()方法后,修改记录的记录数将被返回

你也可以使用create()方法添加一条person记录,它返回的是一个person实例

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

现在有三条people记录在数据库中,那开始添加一个pets吧,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_mittents.delete_instance()

delete_instance()方法的返回值是数据库中被删除的记录数

数据检索

数据库的好处就是它允许我们使用查询语句检索数据,关系型数据库非常适合做即席查询

获取单条数据

在库里检索Grandma’s的记录,为了获取一条记录,使用SelectQuery.get()

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

我们也可以使用等效速记法Model.get()

grandma = Person.get(Person.name == 'Grandma L')
获取多条记录

列出所有person的名字

for person in Person.select():   print person.name,person.relative 

列出所有的cat和它们owner的名字

query = Pet.select().where(Pet.animal_type = 'cat')for cat in query:    print cat.name,cat.owner.name

上面的查询有一个很大的问题,因为我们访问pet.owner.name时,我们没有在原始查询中获取此值,pewwee就不得不再做一次查询,来获取pet的owner。这种行为被称作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

现在我们获取Bob的所有宠物

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

我们可以在这里做另一件很酷的事来得到Bob的宠物。既然我们已经有一个对象来代表Bob,我们可以这样做

for pet in Pet.select().where(Pet.ower == uncle_bob)    print pet.name

为了让这些数据按字母排序,我们可以使用order_by()语句

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

按年龄从小到大列出people

for person in Person.select().order_by(Perso.birthday.desc()):    print person.name, person.birthday

列出所有的people和他们的宠物信息

for person in Person.select():    print person.name, person.pets.count    for pet in person.pets:        print pet.name, pet.animal_type

我们又一次遇到一个n + 1的查询行为的经典例子。我们可以通过执行连接和聚合记录来避免这种情况。

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():    print person.name, person.pets.count    for pet in person.pets:        print pet.name, pet.animal_type

即使我们创建了分开的子查询,但是实际执行了一次查询。
最后,做一次复杂的查询吧,获取生日符合以下条件的people:
- before 1940 (grandma)
- after 1959 (bob)

d1940 = date(1940, 1, 1)d1960 = date(1960, 1, 1)query = (Person.select().where((Person.birthday < d1940) | (Perosn.birthday > d1960)))for person in query:    print person.name, person.birthday

做一次相反的查询,获取在1940年和1960年之间的people

d1940 = date(1940, 1, 1)d1960 = date(1960, 1, 1)query = (Person.select().where((Person.birthday > d1940) & (Perosn.birthday < d1960)))for person in query:    print person.name, person.birthday

做最后一次查询,这里将用到一个SQL函数获取名字开头是’g’|’G’的people

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

数据库操作完毕,需要关闭数据库连接

db.close()

这只是最基本的,你可以让你的查询更复杂。

其他SQL语句也可用,例如
- group_by()
- having()
- limit() and offset()

与现有数据库协同工作

如果你已经有了数据库,你可以使用pwiz(一种模型生成器)自动生成peewee模型;例如,假设我有postgresql数据库,命名为charles_blog,我将执行:

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