美文网首页
Python的魔法ORM --《PonyORM教程》 1.连接,

Python的魔法ORM --《PonyORM教程》 1.连接,

作者: justonlyyo | 来源:发表于2019-10-10 11:20 被阅读0次

    前言

    在非django框架的ORM当中,我们有很多选择,包括大名鼎鼎的重量级选手sqlalchemy和颇受欢迎的轻量级明星peewee,这2者的的介绍和教程网上到处都是,我这里就不介绍了。因为一个偶然的机会,了解到还有一款轻量级的orm---ponyorm, 官网在此https://ponyorm.org。被它的低学习成本和高度抽象化所吸引,本着独乐乐不如众乐乐的原则,特别介绍给大家,😀目的是为了大家在使用python的ORM时有更多的选择

    首先,这是一款战斗民族(俄罗斯)的作品,印象中,俄罗斯的东西都是自带黑魔法属性的,比如 Kaspersky,nginx之流🤣🤣🤣

    相对其他的ORM有以下几个特点:

    • 学习成本低: 没有复杂的声明方式和眼花缭乱的查询语法,使用python原生类型定义字段。入门很容易。
    • 抽象程度高: 对数据库方面的预备知识要求很少,使用起来有种黑魔法的感觉,所以也常被成为只有Python魔法少女才知道的ORM
    • 使用便捷 相比其他的ORM,pony使用更少的代码实现了同样操作。代码简洁,大量的缺省值的设定非常合理,即使是新手,也能写出可靠,简洁的程序。
    • 在线的模型编辑器很上手:在编辑上设计好模型,直接可以生成代码和sql语句,对于小型团队开发,这个非常提升效率。

    好了,下面开始

    以下示范以ubuntu 18.04 + python3.6为例,你的系统可能有所不同。请自行调整。

    安装

    pip install pony
    

    建立数据库连接

    新建一个 pony_db.py 文件,输入如下代码

    # -*- coding: utf-8 -*-
    from pony.orm import *  # 引入
    from datetime import date
    from datetime import datetime
    
    
    setting = {
        "provider": "mysql",    # 声明数据库种类
        "host": "127.0.0.1",    # 数据库主机地址,也可以是域名
        "port": 3306,           # 端口
        "database": "test_db",  # 数据库名
        "user": "test_01",      # 用户名
        "password": "123456",   # 密码
        "charset": "utf8mb4",   # 字符集
    }
    db = Database(**setting)  # 生成数据库引擎
    
    
    class Employee(db.Entity):
        """员工类"""
        _table_ = "employee"
        name = Required(str, max_len=40, unique=False, nullable=False, default="无名氏")  # 姓名
        age = Optional(int, size=8, nullable=True, default=None)  # 年龄
        born = Required(date, nullable=False, column="born_date", default=date.today)  # 🏠出生年月日
    
    
    if __name__ == "__main__":
        db.drop_table(table_name="employee", if_exists=True, with_all_data=True)  # 删除表,演示实体声明时用于快速清除旧表
        db.generate_mapping(create_tables=True)  # 生成实体,表和映射关系
        pass
    

    setting 是数据库的配置声明,这点每什么好记说明的,天下sql几乎都是这么配置的....
    class Employee(db.Entity) 这是我们定义的实体类,这里有一个要求,db.Entity是实体模板类,你的实体类必须继承db.Entity类。

    实体声明

    下面是字段声明:

    • table : 定义表名
    • 字段名: 等号的左边是字段名,也是数据库的表中对应的列的名字,这没啥好说的,当然,如果希望重新定义表中对应的列的名字,可以在后面的字段定义中使用 column="new_name"的方法来定义.
    • 字段种类: Required和Optional是定义字段的种类的声明,pony共有 Required,Optional,PrimaryKey ,Set,和Discriminator5种字段的声明:
    • Required 定义一个创建实例时,必须提供的字段,注意,这里定义的不是数据库的字段的not null选项
    • Optional 定义一个创建实例时,可选的字段,注意,这里定义的不是数据库的字段的not null选项
    • PrimaryKey 定义一个主键的,由于pony默认会声明一个int类型的自增主键,所以这个声明很少用到
    • Set 定义一个几何类型的字段,一般用作一对多的多方和多对多情况的声明。
    • Discriminator 定义一个鉴别字段,用于区别父类和子类的表,这个字段在实体的继承中我们会讲到,现在请无视。
    • 字段类型 字段声明的第一个参数时字段类型,你可以看到,pony没有额外定义字段(当然也不需要你引入各种String,Integer之类的),直接使用python的原生的字段类型进行声明,这些字段类型包括: int, str, date, datetime等(需要数据库支持),
    • 声明参数 字段声明的除第一个参数外,都是对声明的参数进行定义的参数,常用的定义如下:
    • max_len: 字段长度, str 类型特有.
    • size: 数字的大小范围,int类型特有. 8,16,32,64 默认32,对应mysql定义的 INT(11)
    • nullable: 字段的not null选项, Optional声明的字段,这里必须是True,
    • default: 字段的默认值, nullable=True的字段必须是提供默认值,可以时函数的返回值
    • unique: 是否唯一

    生成映射

    db.generate_mapping(create_tables=True)  # 生成实体,表和映射关系
    

    上面这行代码的意思就是创建表,实体类的映射关系 ,这种映射关系非常重要,pony在启动项目时会检查整个项目的所有实体类的映射关系是否正确。所以,随着项目的实体类越来越多,这个检查的过程会越来越漫长。这也是pony为数不多的缺陷之一吧。

    增删改查

        with db_session:
            emp = Employee(name="张三", age=12)  # 创建一个实例
            emp_dict = emp.to_dict()  # 实例转字典
            print(emp_dict)
            emp.set(age=14)  # 修改字段
            emp = Employee.get(name="张三")  # 查找名字叫张三的员工
            print(emp.to_dict())
            emp.delete()  # 删除实例
            emp = Employee.get(name="张三")  # 查找名字叫张三的员工
            print(emp)
    
    • db_session: 这是数据库会话的上下文管理器,操作者必须使用 with 关键字保证对数据库的操作都位于db_session的上下文空间之内(偷偷告诉你,更推荐你用@db_session这个装饰器哦)
    • to_dict: 实体类的实例使用此方法输出dict格式的对象。
    • get: 根据条件,查询一个实例,如果给定的查询条件返回的查询结果不止一个,会抛出 pony.orm.core.MultipleObjectsFoundError: Multiple objects were found. Use Employee.select(...) to retrieve them 的错误提醒,如果你需要查询多个,请使用 select 方法。
    • set: 修改实例的属性,你可以使用 emp.set(**kwargs)的方法一次修改实例的多个属性
    • delete: 没什么好说的,就是删除实例

    例子

    查询多个实例对象
    修改Employee类的代码,增加一个find_many的方法

        @classmethod
        @db_session
        def find_many(cls, **kwargs) -> list:
            """
            根据查询条件查询多个实例对象
            :param kwargs: 查询条件
            :return:
            """
            handler = select(x for x in cls)
            """注意handler的链式调用"""
            for name, val in kwargs.items():
                handler = handler.where(lambda x: getattr(x, name=name) == val)
            result = [x.to_dict() for x in handler]
            return result
    

    表里有如下数据:


    2019-10-09 17-07-47 的屏幕截图.png

    查询

    print(Employee.find_many(age=15))
    print(Employee.find_many(age=15, name='john'))
    
    [{'id': 2, 'name': 'jack', 'age': 15, 'born': datetime.date(2019, 10, 9)}, {'id': 4, 'name': 'john', 'age': 15, 'born': datetime.date(2019, 10, 10)}]
    [{'id': 4, 'name': 'john', 'age': 15, 'born': datetime.date(2019, 10, 10)}]
    Process finished with exit code 0
    

    说明:

    • @classmethod 类方法的装饰器。表明此方法可以直接被类对象调用
    • @db_session 是数据库会话的装饰器,被此装饰器装饰的方法,内部的代码都运行在是数据库会话的上下文之间,这也是pony官方推荐的做法,和使用 with db_session 上下文管理器相比,前者支持事务的嵌套操作。
    • select 查询方法(最常用的查询方法之一),一般用于指定条件查询多个对象,条件一般用 x for x in cls 这样的表达式来指定。有别于需要额外学习的查询语法,这样的表达式本身就是python的表达式,无需额外的学习成本,理解起来也很方表,使用表达式查询是pony的的亮点之一,也是pony高级抽象化的特征.此函数返回一个Query对象,这个对象本身的绝大多数方法的执行结果就是返回self。这样很方便的让用户以链式调用的方式,拼接一个复杂的查询。而Query对象本身就是一个可迭代的对象,可以很方便的用[x for x in handler]类似的方法取出结果集。

    索引

    1. Python的魔法ORM --《PonyORM教程》 1.连接,声明和查询
    2. Python的魔法ORM --《PonyORM教程》 2 实体关系
    3. Python的魔法ORM --《PonyORM教程》 3 实体继承
    4. Python的魔法ORM --《PonyORM教程》 4 高级定义和连接查询

    相关文章

      网友评论

          本文标题:Python的魔法ORM --《PonyORM教程》 1.连接,

          本文链接:https://www.haomeiwen.com/subject/putgpctx.html