Flask框架的学习——07—(Flask操作MySQL数据库、使用ORM对数据库的增删改查操作、SQLAlchemy属性常用数据类型)

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可用参数

  1. 模型对象。指定查找这个模型中所有的对象。
  2. 模型中的属性。可以指定只查找某个模型的其中几个属性。
  3. 聚合函数。
    • 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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章