peewee数据库操作

db.py:

from flask import Flask
from peewee import * 
from playhouse.flask_utils import FlaskDB  #peewee工具
from playhouse.pool import PooledMySQLDatabase  #连接池

app = Flask(__name__)  #在这里创建实例并和peewee绑定

#配置连接池
database = PooledMySQLDatabase(
    database='usdt',
    user='root',
    password='root',
    host='127.0.0.1',
    port=3306,
    max_connections=10,  # 设置最大连接数为10
    stale_timeout=5000,  #超时的连接被自动回收
    charset='utf8mb4'
)

peewee_db = FlaskDB(app,database) #将连接池和app绑定,并赋予peewee_db

#定义模型
class User(peewee_db.Model):
    id = PrimaryKeyField()
    email = CharField(max_length=80, unique=True)
    password = CharField(max_length=160)

User.create_table()  # 创建表

(db.py文件和main.py同目录)
main.py:

from db import User, peewee_db, app #导入模型peewee_db是操作数据库必须导入,app必须导入

db = peewee_db.database  #事务处理上下文,并赋予db
app.config['SECRET_KEY'] = 'SECRET_KEY'  设置密钥

#数据库写入操作一定要使用with方法,自动释放连接
with db.connection_context():
    if User.select().where(User.email == form.email.data): #查询邮箱是否被注册
        flash('该邮箱地址已被注册,请使用其他邮箱地址', 'error')
        return render_template('register.html', form=form)
    
    #开始写入数据
    user = User(email=form.email.data,password=form.password.data,beiyaoqingma=yaoqingma)
    user.save()
    

事务方法

db.atomic() #事务提交,如果不成功就滚回,同写多条数据,且要确保完整性
db.execution_context() #事务提交,但是可以不成功后执行操作,更完善的事务
db.connection_context() #在同一连接提交,一般用这种

写入方法

#直接写入方法,已经可以调用user.id
with db.connection_context():
    user = User.create(email='test@example.com', password='123456')

#查询再写入方法
with db.connection_context():
    user = User.get_or_none(User.email == gemail)  #返回对象或者None
    if user: #判断是否为空
        user.password = '123456'
        user.save()

查询方法

#捕获异常查询
with db.connection_context():
    try:
        user = User.get(User.email == form.email.data)
    except User.DoesNotExist:
        print('产生异常')
        
        
#直接查询,返回一条数据或空
with db.connection_context():
    gouwuche = Gouwuche.get_or_none(id=2)  #返回一条数据,如果没有返回空
    if gouwuche:  #判断是否为空
    gouwuche = gouwuche.prefetch(Sku) #如果存在则预取sku数据
        
#直接查询2,返回所有数据,如果没有则为空
with db.connection_context():
    users = User.select().where(User.email == 'test@example.com')  #注意此方法返回的是一个对象,访问数据要使用users[0].id

    #按某个字段倒序查询:
    gouwuche = Gouwuche.select().where(Gouwuche.user == user_id).order_by(Gouwuche.id.desc())

更新数据方法

#方法1
User.update(email='1111@qq.com').where(User.id == 1).execute()  #email是要改的数据,where中间是指定修改哪条

#方法2
user = User.get(User.id == 1)
user.email = 'new_email@example.com'
user.save()

删除数据

Gouwuche.delete().where(Gouwuche.user == user_id).execute() #删除查询到的所有

#查询再删除
gouwuches = Gouwuche.select().where(Gouwuche.user == user_id)
for gouwuche in gouwuches:
    gouwuche.delete_instance()

外键

通常用于一对多对应关系,例如一个表格内的用户,对应他们的消费记录的表

#被外键模型
class User(peewee_db.Model):
    id = PrimaryKeyField()
    email = CharField(max_length=80, unique=True)
    password = CharField(max_length=160)
    mobi = CharField(max_length=14, null=True, unique=True)
#外键模型
class Jifen(peewee_db.Model):
    user = ForeignKeyField(User, backref='jifens')#参数1绑定表,参数2是可选反向索引,也就是说能通过user.jifens访问到对应的jifen数据
    jifen = CharField(max_length=80)
    xiaofeiid = CharField(max_length=250)
    
#写入外键
jifen = Jifen.create(user=user.id, email='test@example.com', password='password')

# 通过外键反向查询
for jifen in user.jifens:
    print(jifen.xiaofeiid)
    
#查询外键的时候,预取主键数据:
#注意如果还有其他条件,要先写其他条件,这里的prefetch始终在最后,以确保其他的条件先查询
gouwuches = Gouwuche.select().prefetch(Sku) #这是查询购物车的时候,查询Sku商品表对应的数据
# 假设sku表中存在ceshi字段,你已经可以使用gouwuche.sku.ceshi来读取Sku的表了

触发保存事件执行操作

class User(peewee_db.Model):
    id = PrimaryKeyField()
    email = CharField(max_length=80, unique=True)
    password = CharField(max_length=160)
    yaoqingma = CharField()
    
    def set_yaoqingma(self):
        #判断新数据是否有邀请码,没有则生成邀请码
        if not self.yaoqingma:
            #获得随机码
            code = get_suijima()
            #如果随机码已经在表中存在则一直循环重新获得
            while User.select().where(User.yaoqingma == code):
                code = get_suijima()
            #最后把未使用的随机码赋值
            self.yaoqingma = code

    #每次有更新数据时自动对当条数据执行下面函数
    def save(self, *args, **kwargs):
        self.set_yaoqingma() #邀请码检查
        return super().save(*args, **kwargs)

没写入数据之前,获得一个表的下一个自增ID的值

next_id = Dingdanmx.select().order_by(Dingdanmx.id.desc()).get().id + 1

创建表

db.create_tables([User,Shangpin,Sku])

字段类型

PrimaryKeyField:主键字段
CharField:字符串字段,通常用于存储短文本。
TextField:文本字段,通常用于存储长文本。
IntegerField:整数字段,存储整数值。
FloatField:浮点数字段,存储浮点数值。
DoubleField:双精度浮点数字段,存储双精度浮点数值。
BooleanField:布尔字段,存储布尔值(True 或 False)。
DateField:日期字段,存储日期值。
DateTimeField:日期时间字段,存储日期和时间值。
TimeField:时间字段,存储时间值。
DecimalField:十进制字段,存储高精度的十进制数值。
ForeignKeyField:外键字段,定义模型之间的外键关系。
UUIDField:UUID 字段,存储 UUID 值。
BinaryField:二进制字段,存储二进制数据。
BigIntegerField:大整数字段,存储大整数值。
SmallIntegerField:小整数字段,存储小整数值。
BlobField:BLOB 字段,存储二进制大对象。

字段参数

通用参数
null:是否允许字段为空。示例:title = CharField(null=True)
default:字段的默认值。示例:created_at = DateTimeField(default=datetime.now)
index:是否为字段创建索引。示例:email = CharField(index=True)
unique:是否要求字段值唯一。示例:username = CharField(unique=True)
choices:字段的可选值列表。示例:status = CharField(choices=[('draft', 'Draft'), ('published', 'Published')])
constraints:字段的额外约束。示例:age = IntegerField(constraints=[Check('age >= 18')])

特定类型参数
max_length:最大长度(仅适用于 CharField)。
max_digits:最大数字位数(仅适用于 DecimalField)
decimal_places:小数位数(仅适用于 DecimalField)

外键字段参数
引用的模型。ForeignKeyField(User, backref='articles')
反向引用的名称。 ForeignKeyField(User, backref='articles')
删除行为。ForeignKeyField(User, backref='articles', on_delete='CASCADE')