zoukankan      html  css  js  c++  java
  • peewee基本操作

    本文将简单的介绍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
  • 相关阅读:
    Oracle Instant Client(即时客户端) 安装与配置
    面试中经典的数据库问题
    MySQL 大表优化方案
    mysql中Timestamp,Time,Datetime 区别
    HTML学习之给div高度设置百分比不生效的问题
    textarea文本域宽度和高度width及height自动适应实现代码
    JAVA基础----java中E,T,?的区别?
    去除ArrayList集合中的重复自定义对象元素
    sql select中加入常量列
    mysql 将null转代为0
  • 原文地址:https://www.cnblogs.com/zhengze/p/10365564.html
Copyright © 2011-2022 走看看