Python 轻量级ORM框架Peewee的使用指南

1、安装

pip install peewee

2、基础:

初始化数据库:

db = MySQLDatabase('database_name', user='www-data', charset='utf8mb4')

创建model:

class BaseModel(Model):
    class Meta:
        database = db

class User(BaseModel):
    name = CharField(unique = True)
    age = IntegerField()
    sex = CharField()

迁移模型(也叫生成表):

db.connect()
User.create_table() # 也可以使用 db.create_tables([User]),但是建议使用前者迁移模型
db.close()

3、字段类型

以下字段类型对象与之对应的是MySQL中的数据类型
需要对比其他数据库的可以参考官方文档Peewee文档

AutoField:integer
UUIDField:varchar(40)
CharField:varchar
IntegerField:integer
DecimalField:numeric
TextField:text
DateTimeField:datetime
DateField:date
TimeField:time
FixedCharField:char
BigAutoField:bigint
BigIntegerField:bigint
SmallIntegerField:smallint
IdentityField:not supported
FloatField:real
DoubleField:double precision
BlobField:blob
BitField:bigint
BigBitField:blob
BinaryUUIDField:varbinary(16)
TimestampField:integer
IPField:bigint
BooleanField:bool
BareField:not supported
ForeignKeyField:integer
ManyToManyField:无

这些字段常用的基本参数,下面的都是默认设置,实际中根据需求修改:

null = False 是否允许空字符串。
index = False 是否创建普通索引。
unique = False 是否创建唯一索引。
column_name = None 在数据库中指定列的名称,一般不设置会使用定义model时的变量名作为列名。
default = None 设置默认值。
primary_key = False 是否为主键。
constraints = None 增加约束,如果增加,该值是一个列表。
collation = None 用于排序字段或索引的排序规则。
choices = None 设置可选的枚举选项,和Django的ORM射着一样,值是一个元组,元素也是一个元组,例如((1,'女'),(2,'男'))。
help_text = None 设置备注或注释文本。
verbose_name = None 设置一个可读性良好的名称,例如 name = CharField(verbose_name = '用户名')。
index_type = None 指定索引类型,不常用,一般默认即可。

常用字段类型的特殊参数:

CharField、FixedCharField:
max_length = 32 设置给字段最大长度为32,注意CharField的最大max_length=255。
DateTimeField、DateField、TimeField:
formats = '%Y-%m-%d %H:%M:%S' 设置日期时间的格式化,最常用的格式化。
formats = '%Y-%m-%d' 设置日期的格式化,最常用的格式化。
DecimalField:
max_digits = 15 设置要存储的最大位数。
decimal_places = 2 设置最大精度。
auto_round = True 设置自动舍入值。
ForeignKeyField:
model = Model object 这是要引用的model或者外键指向的model,必填。
field = Field 设置外键指向model的具体字段,默认是主键,无特殊需求不用更改,默认即可。
backref = 'str' 设置反向引用的访问器名称,类似于Django中设置外键字段是配置的related_name。
on_delete = 'CASCADE' 设置当被引用的记录删除时,指向该记录的数据操作,存在多个可选值:
	CASCADE 跟随外键一同删除
	RESTRICT 限制外表中的数据删除,就是当外键删除时,检测到有指向该外键的数据,那么就不允许删除。
	SET NULL 设置空值
	SET DEFAULT 设置默认值
	NO ACTION 不做操作,默认的
on_update = 'CASCADE' 和on_delete作用类似,只是on_update实在外键数据修改时触发。
ManyToManyField:对于这个字段,由于peewee支持的不是很好,建议需要多对多model设计时,使用ForeignKeyField建立第三方表实现。
model = Model object 这是要引用的model或者外键指向的model,必填。
backref = 'str' 设置反向引用的访问器名称,类似于Django中设置外键字段是配置的related_name。
on_delete = 'CASCADE' 设置当被引用的记录删除时,指向该记录的数据操作,存在多个可选值:
	CASCADE 跟随外键一同删除
	RESTRICT 限制外表中的数据删除,就是当外键删除时,检测到有指向该外键的数据,那么就不允许删除。
	SET NULL 设置空值
	SET DEFAULT 设置默认值
	NO ACTION 不做操作,默认的
on_update = 'CASCADE' 和on_delete作用类似,只是on_update实在外键数据修改时触发。

模型选项和表元数据 - class Meta的设置:
database 设置模型使用的数据库,可以通过继承设置。也就意味着我们可以写一个基本的model,然后其他model都继承自这个基本model。

示例:

class UserModel(Model):
	name = CharField(unique = True)
    age = IntegerField()
    sex = CharField()
    class Meta:
        database =  MySQLDatabase('my_database')

table_name 设置表名,不可以通过继承设置。如果不想使用默认值,每个model在编写时需要手动设置。
示例:

class UserModel(Model):
	name = CharField(unique = True)
    age = IntegerField()
    sex = CharField()
	class Meta:
		table_name = 'user_table'

table_function 可以设置一个函数用来动态生成表名的功能。可以通过继承设置。
示例:

def make_table_name(model_class):
    model_name = model_class.__name__
    return model_name.lower() + '_tbl'

class BaseModel(Model):
    class Meta:
        table_function = make_table_name

class User(BaseModel):
    # table_name will be "user_tbl".

class UserProfile(BaseModel):
    # table_name will be "userprofile_tbl".

indexes 设置要索引的字段列表,可以设置联合索引,类似Django的联合索引设置。可以通过继承设置。

class Transaction(Model):
    from_acct = CharField()
    to_acct = CharField()
    amount = DecimalField()
    date = DateTimeField()

    class Meta:
        indexes = (
            # create a unique on from/to/date
            (('from_acct', 'to_acct', 'date'), True),

            # create a non-unique on from/to
            (('from_acct', 'to_acct'), False),
        )

primary_key 设置复合主键。可以通过继承设置。
示例:

class BlogToTag(Model):
    """A simple "through" table for many-to-many relationship."""
    blog = ForeignKeyField(Blog)
    tag = ForeignKeyField(Tag)

    class Meta:
        primary_key = CompositeKey('blog', 'tag')

constraints 设置表约束列表。可以通过继承设置。
示例:

class Person(Model):
    first = CharField()
    last = CharField()

    class Meta:
        primary_key = CompositeKey('first', 'last')

class Pet(Model):
    owner_first = CharField()
    owner_last = CharField()
    pet_name = CharField()

    class Meta:
        constraints = [SQL('FOREIGN KEY(owner_first, owner_last) '
                           'REFERENCES person(first, last)')]

4、基于User模型的增删改查:

一:新增

1、create
user = User.create(name='张三',age=26,sex='男') # 创建一个记录,并返回一个user对象
2、save
user = User(name='张三',age=26,sex='男')
user.save() # 创建一个记录,并返回一个user对象
3、insert
user_id = User.insert(name='张三',age=26,sex='男').execute()  # 创建一个记录,并返回新纪录的主键
这里使用了 execute() 方法,因为insert不会马上执行,execute()方法可以马上执行操作。
4、insert_many
User.insert_many([
    ('张三丰', 26, '男'),
    ('王大胖', 12, '男'),
    ('王小小', 22, '女')
],
    ['name', 'age', 'sex']
).execute()
也可以插入字典列表
User.insert_many([
    {
    
    'name': 王二小', 'age': 12, 'sex': '男'},
    {
    
    'name': 王小小', 'age': 13, 'sex': '女'},
    {
    
    'name': 王大胖', 'age': 15, 'sex': '男'}
]).execute()
5、bulk_create
和Django类似的批量创建
users = [
    {
    
    'name': 王二小', 'age': 12, 'sex': '男'},
    {
    
    'name': 王小小', 'age': 13, 'sex': '女'},
    {
    
    'name': 王大胖', 'age': 15, 'sex': '男'}
]
datas = [User(**item) for item in users]
# 不使用事务
User.bulk_create(datas) 
# 使用事务
with db.atomic():
    User.bulk_create(datas)

二、查询

1、get 和 get_or_none
user = User.get(User.id==1) # 当获取的结果不存在时,报 Model.DoesNotExist 异常。如果有多条记录满足条件,返回第一条。
user = User.get_or_none(User.id==1) # 和get的区别是,当没有匹配数据时返回None,不会抛出异常。
2、get_by_id
user = User.get_by_id(1) # 对于主键查找可以用这个
3、get_or_create
user, created = User.get_or_create(name='张三', defaults={
    
    'age': 26, 'sex': '男'}) # 如果存在就返回user,不存在就创建后再返回user
4、select
使用 Model.select() 查询获取多条数据。select 后可以添加 where 条件,如果不加则查询所有数据。
user = User.select() # 查询user内的所有数据,查询所有列
user = User.select(User.id, User.name) # 查询列为id、name,返回所有数据
带where条件的:
where语句中查询运算符:
## 与或非逻辑运算符:
&	与	示例:(User.is_active == True) & (User.is_admin == True)
| 	或	示例:(User.is_admin) | (User.is_superuser)
~	非	示例:~(User.username.contains('admin'))
比较运算符:
==	等于
<	小于
<=	小等于
>	大于
>=	大等于
!=	不等于
<<	x IN y,其中y是列表或查询
>>	x IS y,其中y可以是None / NULL,例如判断obj_id >> None 相当于SQL语句:obj_id is NULL
%	x喜欢y,其中y可能包含通配符
**	x像y,其中y可能包含通配符
^	异或
~	一元否定(例如,NOT x)
## 和MySQL查询的一些运算符:
.in_(value)		IN查找(与相同<<)。
.not_in(value)	不在查询中。
.is_null(is_null)	IS NULL或IS NOT NULL。接受布尔参数。
.contains(substr)	通配符搜索子字符串。相当于 LIKE '%xx%'
.startswith(prefix)	搜索以开头的值prefix。
.endswith(suffix)	搜索以结尾的值suffix。
.between(low, high)	在low和之间搜索值high。
.regexp(exp)	正则表达式匹配(区分大小写)。
.iregexp(exp)	正则表达式匹配(不区分大小写)。
.bin_and(value)	二进制AND。
.bin_or(value)	二进制或。
.concat(other)	使用串联两个字符串或对象||。
.distinct()		标记列以进行DISTINCT选择。
.collate(collation)	用给定的排序规则指定列。
.cast(type)		将列的值强制转换为给定的类型。

示例:
user = User.select().where(User.name == '张三') # 查询所有叫张三的数据
user = User.select().where(User.name == '张三', User.age = 26) # 查询名字叫张三并且年龄为26的数据
user = User.select().where((User.name == '张三') | (User.age = 26)) # 查询名字叫张三或者年龄为26的数据
user = User.select().where(~User.age == 26)# 查询年龄不等于26的数据
user = User.select().where(User.age != 26)# 查询年龄不等于26的数据
user = User.select().where(User.age >= 26)# 查询年龄大等于26的数据
user = User.select().where(User.age in [24,26,27]) # 查询年龄在[24,26,27]内的数据
user = User.select().where(User.name.contains('张三')) # 模糊查询,相当于 LIKE '%张三%'
排序:
user = User.select().order_by(User.id) # 默认升序 == order_by(User.id.asc())
user = User.select().order_by(-User.id) # 降序排序 == order_by(User.id.desc())
取出前N个数据:
user = User.select().order_by(-User.id).limit(10) # 取出id从大到小的前10个数据
计数count:
tatol = User.select().count() # 统计所有数据条数
分页查询:
user = User.select().order_by(User.id).paginate(2, 10) # paginate(page, page_size) 查出第二页,每页10条数据
分组聚合查询:
query = User.select(User.age, fn.Count(User.id).alias('count')).group_by(User.age)
假设现在有三个表分别为:
class Photo(Model):
    image = CharField()

class Tag(Model):
    name = CharField()

class PhotoTag(Model):
    photo = ForeignKeyField(Photo)
    tag = ForeignKeyField(Tag)

query = (Tag.select().join(PhotoTag).join(Photo).group_by(Tag).having(fn.Count(Photo.id) > 5))

三、修改

1、save
user = User.get(User.id==1)
user.age = 18
user.save()
2、update
user = User.update(age=18).where(User.name=='张三').execute() # update用于批量更新,将所有匹配结果进行更新
User.update(age=User.age + 1).execute() # 批量操作,会将所有人的年龄加一后再储存

四、删除

1、delete
User.delete().where(User.id == 1).execute() # 可以应用批量删除
User.delete().where(User.age < 18).execute() # 可以删除所有年龄小于18的数据行
2、delete_instance
user = User.get(User.id=1) # 针对已经知道明确的对象时,可以应用该删除方法更好些,可以避免误删。
user.delete_instance()

使用事务:使用事务可以保证原子性等事务的四大特性
with db.atomic():
    # 执行相关SQL操作
    user = User.get(User.id=1)
    user.age = 18
    user.save()

猜你喜欢

转载自blog.csdn.net/haeasringnar/article/details/107674096