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)

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