注意,pypadb 0.1.14 版本破坏性变更。

命名更改:
pypadb.conf.db_configurer    -> pypadb.conf.db    (module)
pypadb.conf.table_configurer -> pypadb.conf.table (module)

pypadb.conf.db.DbConfigurer   -> pypadb.conf.db.DbConfig       (class)
pypadb.conf.table.TableConfig -> pypadb.conf.table.TableConfig (class)

pypadb.conf.db.db_configurer -> pypadb.conf.db.db_config     (attribute)
pypadb.conf.table.tables     -> pypadb.conf.table.table_pool (attribute)

pypadb 提供了 @insert@update@delete@select 四个装饰器来扩展函数。

有如下表结构:

create table test
(
    id      int unsigned auto_increment primary key,
    content varchar(255) null,
    ctime   bigint       null,
    mtime   bigint       null
);

实体类如下:

class Test(BaseModel):
    id: Optional[int]
    content: str
    ctime: Optional[int]
    mtime: Optional[int]
  • 实体类须继承 pydantic.BaseModel
  • 实体类的属性须添加类型注释。
  • 可以为 None 的属性或- 不在数据库表里的属性须用 Optional 包裹。

@insert

from pypadb.decorator import insert

@insert('insert into test(content,ctime)')
def ins_test(test: Union[list[Test], Test]):
    # 在 insert 前修改 ctime(创建时间)为当前时间
    test.ctime = int(datetime.datetime.now().timestamp() * 1000)

# 单个插入
ins_test(Test(content='wow'))
# 批量插入
ins_test([Test(content='wow'), Test(content='123456')])

@insert 装饰器接受一个参数 sql: str,要表明插入时的列名。

被装饰的函数只接受一个参数,可以为 Test 或者 list[Test],装饰器在处理的时候会判断是否进行批量插入。

函数体可以为 pass,如果函数体不为空,则会在插入前调用函数,例如上面的代码,在插入前初始化 ctime 字段为当前时间。对于 list[Test],装饰器同样会在插入前对每一个实体类进行处理。

函数的返回值是修改的最后一行主键值。

@update

from pypadb.decorator import update

@update('update test')
def upd_test(test: Test):
    # 在 update 前修改 mtime (修改时间)为当前时间
    test.mtime = int(datetime.datetime.now().timestamp() * 1000)

# 实体类,查询条件1,查询条件2 ...
upd_test(Test(content='wuhu'), id=1)

@update 接受一个参数 sql: str,只需要写上需要更新的表,装饰器会根据传进来的实体对象动态生成 sql 语句。即实体对象的属性值为 None、空数组或者空字符串时,@update 会忽略这一属性。需要注意的是,若属性值为 0 时,@update 也会进行更新。

函数体可以为 pass,如果函数体不为空,则会在插入前调用函数,例如上面的代码,在插入前初始化 mtime 字段为当前时间。对于 list[Test],装饰器同样会在插入前对每一个实体类进行处理。

被装饰的函数接受一个参数作为实体对象,还有若干指定参数作为查询条件。

函数的返回值是修改时的主键值。

@delete

from pypadb.decorator import delete

@delete('delete from test where id=%(id)s')
def del_test(id: int = 0):
    pass

@delete 装饰器接受一个值 sql: str,要写全。装饰器会把函数的参数列表和调用函数传进来的值做匹配,处理成一个 dict 交给 pymysql 处理。

@delete 同样支持在删除前调用被装饰的函数。

@select

from pypadb.decorator import select

# 查询返回单个对象
@select('select * from test where id=%(id)s', data_type=Test)
def sel_test_one(id: int) -> Test:
    pass

# 查询返回数组
@select(
    'select * from test where content  like concat(\'%%\',%(concat)s,\'%%\')',
    data_type=Test
)
def sel_test_many(concat: str) -> list[Test]:
    pass

@select 装饰器接受 2 个参数,处理 sql 语句和 @delete 一样,第二个参数 data_type 是为了将查询出来的数据包装成对象。

@select 装饰器会通过反射的方式拿到函数返回值的类型注释,判断其是否为 list 来决定返回值是否为 list。若查询结果有多个,函数的返回值类型注释不是 list 的话,装饰器只会取结果集中的首行包装成对象返回。

被装饰的函数不需要有函数体,对函数体不做处理。被装饰的函数的参数列表不需要加上类型注释,当然加了更严谨。

2022-01-29