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