A guide to using Peewee, a lightweight ORM framework for Python

1. Installation

pip install peewee

2. Basics:

Initialize the database:

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

Create a model:

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

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

Migration model (also called generation table):

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

3. Field type

The following field type objects correspond to the data types in MySQL. If
you need to compare other databases, you can refer to the official document Peewee document

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:无

The basic parameters commonly used in these fields, the following are the default settings, which can be modified according to actual needs:

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 指定索引类型,不常用,一般默认即可。

Special parameters for common field types:

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实在外键数据修改时触发。

Model options and table metadata - class Meta settings:
database Set the database used by the model, which can be set through inheritance. That means we can write a basic model, and then other models inherit from this basic model.

Example:

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

table_name sets the table name, which cannot be set through inheritance. If you don't want to use the default value, each model needs to be set manually when writing.
Example:

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

table_function can set a function to dynamically generate table names. Can be set via inheritance.
Example:

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 Set the list of fields to be indexed, and you can set a joint index, similar to Django's joint index setting. Can be set via inheritance.

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 sets the composite primary key. Can be set via inheritance.
Example:

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 sets the list of table constraints. Can be set via inheritance.
Example:

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. Addition, deletion, modification and query based on the User model:

One: add

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)

2. Query

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))

3. Modify

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() # 批量操作,会将所有人的年龄加一后再储存

4. Delete

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()

Guess you like

Origin blog.csdn.net/haeasringnar/article/details/107674096