• 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
  • 相关阅读:
    WCF Server Console
    Restart IIS With Powershell
    RestartService (recursively)
    Copy Files
    Stopping and Starting Dependent Services
    多线程同步控制 ManualResetEvent AutoResetEvent MSDN
    DTD 简介
    Using Powershell to Copy Files to Remote Computers
    Starting and Stopping Services (IIS 6.0)
    java中的NAN和INFINITY
  • 原文地址:https://www.cnblogs.com/zhengze/p/10365564.html
Copyright © 2020-2023  润新知