1、Flask操作MySQL数据库
在上一篇博客中创建完数据表,并且做完和数据库的映射后,接下来让我们添加数据进去。
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker # sessionmaker是一个类
# 127.0.0.1
HOSTNAME = "localhost"
DATABASE = "python_01"
PORT = 3306
USERNAME = "root"
PASSWORD = "root"
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 创建引擎并生成Base类
engine = create_engine(DB_URL)
Base = declarative_base(engine)
# 必须继承Base类
class Article(Base):
__tablename__ = "article" # 在python_01数据库中创建article这个表
id = Column(Integer, autoincrement=True, primary_key=True) #
name = Column(String(50), nullable=False) # nullable=False非空 字符串50长度
# 模型映射到数据库中
Base.metadata.create_all()
# 实例化
article = Article(name="abcd") # 相当于数据库中的一条记录
article1 = Article(name="python") # 多个数据进行添加
print(article.name)
print(article.id) # None,因为该数据还没有保存到数据库中,所以不会产生
# 创建的数据插入到数据库中。和数据库打交道的,是一个叫做Session的对象
# 保存到数据库 实例化这个类 绑定引擎
Session = sessionmaker(bind=engine)
# 源码中的魔术方法__call__():将这个类当做函数去调用
session = Session()
# 添加数据
# session.add(article) # 添加一个数据
session.add_all([article, article1]) # 添加多个数据
# 提交
session.commit()
print(article.name)
print(article.id) # 这里的id会有值,因为数据库中数据已经生成了
为什么添加到session中后还要做一次commit操作呢,这是因为:
在SQLAlchemy的ORM实现中,在做commit操作之前,所有的操作都是在事务中进行的,因此如果你要将事务中的操作真正的映射到数据库中,还需要做commit操作。
既然用到了事务,这里就并不能避免的提到一个回滚操作了,那么看以下代码展示了如何使用回滚。
2、 使用ORM对数据库的增删改查操作
查找操作是通过session.query()方法实现的,这个方法会返回一个Query对象,Query对象相当于一个数组,装载了查找出来的数据,并且可以进行迭代。具体里面装的什么数据,就要看向session.query()方法传的什么参数了,如果只是传一个ORM的类名作为参数,那么提取出来的数据就是都是这个类的实例。
# -*- encoding: utf-8 -*-
"""
@File : flask_mysql_curd.py
@Time : 2020/4/21 21:07
@Author : chen
"""
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 127.0.0.1
HOSTNAME = "localhost"
DATABASE = "python_01"
PORT = 3306
USERNAME = "root"
PASSWORD = "root"
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 创建引擎并生成Base类
engine = create_engine(DB_URL)
Base = declarative_base(engine)
# 必须继承Base类
class Article(Base):
__tablename__ = "article_test" # 在python_01数据库中创建article_test这个表
id = Column(Integer, autoincrement=True, primary_key=True) #
title = Column(String(50), nullable=False) # nullable=False非空 字符串50长度
content = Column(String(50))
author = Column(String(50))
# 直接打印对象会调用__str__方法
def __str__(self):
return "Article(title:{},content:{},author:{})".format(self.title, self.content, self.author) # 注意这里的self
# 模型映射到数据库中 模型映射完成之后可以不用运行这句了
Base.metadata.create_all()
Sessioner = sessionmaker(bind=engine)
session = Sessioner()
# 添加数据
def add_data():
article = Article(title='python', content='人生苦短', author='龟叔') # 给对应的数据
article1 = Article(title='java', content='xxxxx', author='123') # 给对应的数据
article2 = Article(title='C++', content='xxxxx', author='123') # 给对应的数据
# session.add(article)
# session.add_all([article,article1,article2....]) # 添加多条语句
session.add_all([article, article1, article2]) # 添加多条语句
session.commit()
# 搜索符合条件的数据
def search_data():
# 查询功能query
data = session.query(Article).all() # 查询Article中的所有数据 .all()注意括号要写
for item in data:
# print(item.title)
# print(item.content)
print(item) # 采用类中的__str__方法打印类对象之后就不用逐个打印数据库中的字段了
# print(data)
print("---------------------------------------------------------------------")
# 有条件查询 查询Article.title == 'C++'的数据 filter()函数进行查询
data = session.query(Article).filter(Article.title == 'C++').all() # 返回的是列表
for i in data:
print(i)
print("#"*20)
# filter_by(title="java") 注意这里的查询语句和上面的filter的不同
data = session.query(Article).filter_by(title="java").all() # 返回的是列表
for item in data:
print(item)
print("……"*20)
# 查询第一条 使用频率高
data = session.query(Article).first()
print(data)
print("%" * 20)
# 查询第二,第四条,当数据不存在时候,返回None
# data = session.query(Article).get(2)
data = session.query(Article).get(4)
data1 = session.query(Article).get(5)
print(data)
print(data1)
# 修改数据库中的文件
def update_data():
# 先查询出要修改的数据
article = session.query(Article).first()
article.title = "coder" # 修改数据
print(article.title) # 查看数据是否修改,但是在数据库中需要先进行提交commit()
session.commit() # 提交,此时数据库中的数据才会被修改
# 删除数据库中的文件,不建议使用删除,数据容易误操作
def delete_data():
# 先查询出要删除的数据
article = session.query(Article).first()
session.delete(article) # 删除数据,此时数据库中的数据没有变化,因为没有提交,数据属于假删除,文件安全
session.commit() # 提交,此时数据库中的数据才会被删除,此时数据文件不会恢复,
"""
此时一般会给数据一个字段 is_delete,赋值0或1,代表需要删除,和不需要删除
查询语句时候,只需要多添加一个查询语句is_delete==1或者is_delete==0就行
此时的数据文件比较安全,不会产生误操作,不会丢失
"""
print("!"*30)
# 回滚
article = session.query(Article).first()
article.title = "coder" # 修改数据
print(article.title) # 数据回滚前 coder
session.rollback() # 数据回滚恢复
print(article.title) # 数据回滚后 python 数据恢复必须要在提交之前,才有效果
session.commit() # 提交
if __name__ == '__main__':
# add_data()
# search_data()
# update_data()
delete_data()
还可以对查找的结果(Query)做切片操作
for instance in session.query(User).order_by(User.id)[1:3]
print(instance)
如果想对结果进行过滤,可以使用filter_by和filter两个方法,这两个方法都是用来做过滤的,区别在于,filter_by是传入关键字参数,filter是传入条件判断,并且filter能够传入的条件更多更灵活.
# 第一种:使用filter_by过滤:
for name in session.query(User.name).filter_by(fullname='Ed Jones'):
print(name)
# 第二种:使用filter过滤:
for name in session.query(User.name).filter(User.fullname=='Ed Jones'):
print(name)
3、SQLAlchemy属性常用数据类型
sqlalchemy常用数据类型
- Integer:整形。
- Float:浮点类型。
- Boolean:传递True/False进去。
- DECIMAL:定点类型。
- enum:枚举类型。
- Date:传递datetime.date()进去。
- DateTime:传递datetime.datetime()进去。
- Time:传递datetime.time()进去。
- String:字符类型,使用时需要指定长度,区别于Text类型。
- Text:文本类型。
- LONGTEXT:长文本类型。
from sqlalchemy import create_engine, Column, String, Float, Integer, DECIMAL, Boolean, Enum, DATE, DATETIME, TIME
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime # 导入时间
from sqlalchemy.dialects.mysql import LONGTEXT # 导入长文本
# 127.0.0.1
HOSTNAME = "localhost"
DATABASE = "python_01"
PORT = 3306
USERNAME = "root"
PASSWORD = "root"
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 创建Base类
engine = create_engine(DB_URL)
Base = declarative_base(engine)
# 必须继承Base类
class User(Base):
__tablename__ = 'user'
id = Column(Integer, autoincrement=True, primary_key=True) #
name = Column(String(50), nullable=False) # nullable=False非空 字符串50长度
# price = Column(Float)
# DECIMAL(总共多少位数,保留几位小数)
price = Column(DECIMAL(20, 8)) # 这里要注意数据库类型是innodb
# 布尔类型
is_delete = Column(Boolean)
# 性别 枚举类型 默认为男
gender = Column(Enum('男', '女'), default='男')
# 时间 Date:年月日 DateTime:年月日 时分秒 Time:时分秒
time = Column(DATETIME)
# 文本 Text:文本类型。 LONGTEXT:长文本类型(一般用于新闻)
longtext = Column(LONGTEXT)
'''
sqlalchemy常用数据类型
• Integer:整形。
• Float:浮点类型。
• Boolean:传递True/False进去。
• DECIMAL:定点类型。
• Enum:枚举类型。
• Date:传递datetime.date()进去。 年月日
• DateTime:传递datetime.datetime()进去。 年月日 时分秒
• Time:传递datetime.time()进去。 时分秒
• String:字符类型,使用时需要指定长度,区别于Text类型。
• Text:文本类型。
• LONGTEXT:长文本类型。
'''
# 删除
Base.metadata.drop_all() # 先删除之前创建的映射,才能重新创建新的不同字段的数据表
# 模型映射
Base.metadata.create_all() # 重新创建新的不同字段的数据表
# 实例化
Sessioner = sessionmaker(bind=engine)
# 调用类中的方法__str__进行打印数据,使类变成方法
session = Sessioner()
user = User(name='abc', price='123.456789', is_delete=True, gender='女', time=datetime(2020, 4, 18, 10, 30, 30), longtext='长文本,可编辑')
user1 = User(name='abcd', price='123.4', is_delete=False, time=datetime(2020, 4, 19, 10, 50, 00), longtext='文本,可编辑')
print(datetime.now()) # 现在时间
session.add_all([user, user1]) # 注意这里如果添加多组数据,需要用add_all
# session.add(user)
session.commit()
注意数据库类型是innodb,否则在DECIMAL数据类型中会出现异常。
Column常用参数
- default:默认值。
- nullable:是否可空。
- primary_key:是否为主键。
- unique:是否唯一。
- autoincrement:是否自动增长。
- onupdate:更新的时候执行的函数。
- name:该属性在数据库中的字段映射。
# name:该属性在数据库中的字段映射。直接在Column中添加第一个参数,即把数据库中的字段进行修改
name = Column('fullname', String(50), nullable=False)
# onupdate:更新的时候执行的函数。onupdate=也可以添加函数,实现一些功能 只有修改记录的时候,该参数才有效
update_time = Column(DATETIME, onupdate=datetime.now())
整体代码如下:
from sqlalchemy import create_engine, Column, String, Float, Integer, DECIMAL, Boolean, Enum, DATE, DATETIME, TIME
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime # 导入时间
from sqlalchemy.dialects.mysql import LONGTEXT # 导入长文本
# 127.0.0.1
HOSTNAME = "localhost"
DATABASE = "python_01"
PORT = 3306
USERNAME = "root"
PASSWORD = "root"
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 创建Base类
engine = create_engine(DB_URL)
Base = declarative_base(engine)
# 必须继承Base类
class User(Base):
__tablename__ = 'user'
id = Column(Integer, autoincrement=True, primary_key=True)
# name:该属性在数据库中的字段映射。直接在Column中添加第一个参数,即把数据库中的字段进行修改
name = Column('fullname', String(50), nullable=False) # nullable=False非空 字符串50长度
# price = Column(Float)
# DECIMAL(总共多少位数,保留几位小数)
price = Column(DECIMAL(20, 8))
# 布尔类型
is_delete = Column(Boolean)
# 性别 枚举类型 默认为男
gender = Column(Enum('男', '女'), default='男')
# 时间 Date:年月日 DateTime:年月日 时分秒 Time:时分秒
time = Column(DATETIME)
# 文本 Text:文本类型。 LONGTEXT:长文本类型(一般用于新闻)
longtext = Column(LONGTEXT)
# onupdate:更新的时候执行的函数。onupdate=也可以添加函数,实现一些功能 只有修改记录的时候,该参数才有效
update_time = Column(DATETIME, onupdate=datetime.now())
'''
sqlalchemy常用数据类型
• Integer:整形。
• Float:浮点类型。
• Boolean:传递True/False进去。
• DECIMAL:定点类型。
• Enum:枚举类型。
• Date:传递datetime.date()进去。 年月日
• DateTime:传递datetime.datetime()进去。 年月日 时分秒
• Time:传递datetime.time()进去。 时分秒
• String:字符类型,使用时需要指定长度,区别于Text类型。
• Text:文本类型。
• LONGTEXT:长文本类型。
'''
'''
**Column常用参数**
- default:默认值。
- nullable:是否可空。
- primary_key:是否为主键。
- unique:是否唯一。
- autoincrement:是否自动增长。
- onupdate:更新的时候执行的函数。
- name:该属性在数据库中的字段映射。
'''
# 删除
Base.metadata.drop_all() # 先删除之前创建的映射,才能重新创建新的不同字段的数据表
# 模型映射
Base.metadata.create_all() # 重新创建新的不同字段的数据表
# 实例化
Sessioner = sessionmaker(bind=engine)
# 调用类中的方法__str__进行打印数据,使类变成方法
session = Sessioner()
user = User(name='abc', price='123.456789', is_delete=True, gender='女', time=datetime(2020, 4, 18, 10, 30, 30), longtext='长文本,可编辑')
user1 = User(name='abcd', price='123.4', is_delete=False, time=datetime(2020, 4, 19, 10, 50, 00), longtext='文本,可编辑')
print(datetime.now()) # 现在时间
session.add_all([user, user1]) # 注意这里如果添加多组数据,需要用add_all
# session.add(user)
session.commit()
print('*'*30)
user = session.query(User).first()
print(user)
user.name = "xxx" # 修改数据文件,onupdate参数进行记录
session.commit()
query可用参数
- 模型对象。指定查找这个模型中所有的对象。
- 模型中的属性。可以指定只查找某个模型的其中几个属性。
- 聚合函数。
• func.count:统计行的数量。
• func.avg:求平均值。
• func.max:求最大值。
• func.min:求最小值。
• func.sum:求和。
for i in range(6):
article = Article(title="title%s" % i, price=random.randint(1, 50))
seeeion.add(article)
seeeion.commit()
articles = seeeion.query(Article).all()
print(articles)
for article in articles:
print(article.title)
'''
1. 聚合函数。
• func.count:统计行的数量。
• func.avg:求平均值。
• func.max:求最大值。
• func.min:求最小值。
• func.sum:求和。
'''
from sqlalchemy import func
# 聚合函数
# result = seeeion.query(func.count(Article.id)).first() # 不加first,会显示原生SQL语句:SELECT count(article1.id) AS count_1 FROM article1
# print(result)
# result = seeeion.query(func.avg(Article.price)).first()
# print(result)
# result = seeeion.query(func.max(Article.price)).first()
# print(result)
result = seeeion.query(func.sum(Article.price)).first()
print(result)