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)