Flask-SQLAlchemy
- flask用於orm操作表,一般使用flask- sqlalchemy .操作簡單,易於上手。
1.安裝
pip instal flask-sqlalchemy
2.配置信息
# 數據庫配置
DB_USERNAME = 'root'
DB_PASSWORD = 123
DB_HOST = '127.0.0.1'
DB_PORT = 3306
DB_NAME = 'sql_learn'
DB_URI = "mysql+pymysql://%s:%s@%s:%s/%s?charset=utf8" % (
DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAME
)
# 連接數據庫
SQLALCHEMY_DATABASE_URI= DB_URI
# 如果設置True,會消耗額外內存空間,它用於追蹤對象修改並發送信號
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 調試設置為True
SQLALCHEMY_ECHO = True
SQLALCHEMY_POOL_TIMEOUT #連接超時時間
SQLALCHEMY_POOL_SIZE 數據庫池大小,default=5
3.表的創建
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from exts import db #這里需要引入實例化的SQLAlchemy對象
"""
以下表關系:
一個用戶對應多篇文章(一對多)
一篇文章對應多個標簽,一個標簽對應多個文章(多對多)
"""
"""
一對一關系中,需要設置relationship中的uselist=Flase,其他數據庫操作一樣。
一對多關系中,外鍵設置在多的一方中,關系(relationship)可設置在任意一方。
多對多關系中,需建立關系表,設置 secondary=關系表
"""
# 用戶表
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(50))
email = db.Column(db.String(50))
# 關系表(多對多)
article_tag_table = db.Table('article_tag',
db.Column('article_id', db.Integer, db.ForeignKey('article.id'), primary_key=True),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True))
# 文章表
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(100))
content = db.Column(db.Text)
# 關聯字段,讓author_id外鍵關聯User表id. 這里ForeignKey一定要表名.id
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
# 這里不是字段,而是讓Article與User表創建關聯關系,backref是反向關聯關鍵字
author = db.relationship("User", backref="articles")
tags = db.relationship("Tag", secondary=article_tag_table, backref='tags')
# 標簽表
class Tag(db.Model):
__tablename__ = 'tag'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(50))
Tags表與Article通過第三張表建立多對多關系,通過Article表中tags字段(relationship方法),建立多對多關系:
secondary 多對多關聯類
cascade:設置級聯關系。 刪除可用delete,delete-orphan
single_parent:讓級聯關機支持多對多
passive_deletes :支持關聯(被動)刪除
# 則上面tags字段可以寫成:
tags = db.relationship("Tag", secondary=article_tag_table, backref='tags',cascade="delete, delete-orphan", single_parent=True, passive_deletes=True)
Integer 整型
String 字符串
Text 文本
DateTime 日期
Float 浮點型
Boolean 布爾值
PickleType 存儲一個序列化Pickle 后對象。
4.數據庫遷移
from flask import Flask
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
import config
from exts import db
# 實例化Flask對象
app = Flask(__name__)
# 配置信息加載
app.config.from_object(config)
# SQLAlchemy對象綁定app
db.init_app(app)
manager = Manager(app)
Migrate(app,db)
# 通過命令行形式遷移數據庫
manager.add_command("db",MigrateCommand)
if __name__ == '__main__':
manager.run()
- 數據庫手動創建庫。這里我命名的庫名sql_learn,在Terminal終端執行命令:
python3 manage.py db init #初始化migrate
python3 manage.py db migrate #生成遷移記錄
python3 manage.py db upgrade #提交更新至數據庫
python manage.py db history #查看歷史
python manage.py db downgrade 6af28765840d #回退版本
5.單一的增刪改查
# 增加:
user = User(id=1,username="ming",email="123@163.com")
db.session.add(user)
db.session.commit()
# 修改數據 先執行查,再執行修改,相當於2條SQL語句
user = User.query.filter(User.username=="ming").first()
user.email = "abc@163.com"
db.session.commit()
# 修改方式1 只執行一條更新sql
db.session.query(User).filter_by(username="Limong").update({"email":"8888@163.com"})
# 修改方式2 只執行一條更新sql
User.query.filter(User.username == 'ming').update({'email': 'ABC@163.com'})
db.session.commit()
# 刪除方式
User.query.filter(User.username == "ming").delete()
db.session.commit()
# 查詢:
# 查詢所有:
result = User.query.all()
print(result)
# 根據主鍵查詢
result = User.query.get(1)
# 條件查
result = User.query.filter_by(username="ming").first()
# 多條件查詢
result = User.query.filter(and_(User.username=='name', User.email=='passwd')).all()
# 比較查詢
User.query.filter(User.id.__lt__(5)).all() # 小於5
User.query.filter(User.id.__le__(5)) # 小於等於5
User.query.filter(User.id.__gt__(5)) # 大於5
User.query.filter(User.id.__ge__(5)) # 大於等於5
# in查詢
User.query.filter(User.id.in_([1,2,3,4,5])).all()
# 排序
result = User.query.order_by("id").all()
# 限制查詢 # 查詢id>2,並跳過前2條,總共查3條數據
result = User.query.filter(User.id.__gt__(2)).offset(2).limit(3)
6.一對多關系
6.1數據增加
# 添加一個文章標題是:python基礎, 作者是xu
create_obj = db.session.query(User).filter(User.username=="xu").first()
article = Article(
title="python基礎",
author_id=create_obj.id,
content = "python入門,變量,函數,面向對象..."
)
db.session.add(article)
db.session.commit()
# 通過定義relationship
# 1.在Article 表中添加數據,
# 2.在User表中添加一條數據,並將User表中剛剛添加數據的id,添加到Article中,使其關聯起來
create_obj = Article(
title="python基礎2",
content="python中生成器,迭代器...",
author=User(username="wenfeng",email="123@163.com")
)
db.session.add(create_obj)
db.session.commit()
# 創建User對象
create_obj = User(username = "sun",email="123@163.com")
# 通過對象.backref定義名字,向Article添加2條數據。
create_obj.articles = [
Article(title="python進階1",content="內存管理機制"),
Article(title="python進階2",content="垃圾回收機制")
]
db.session.add(create_obj)
db.session.commit()
db.session.close()
6.2數據查詢
# 查詢所有文章,然后顯示文章名,文章內容,--->連表作者名,作者email
article_list = db.session.query(Article).all()
for row in article_list:
print(row.title,row.content,row.author.username,row.author.email)
user_list = db.session.query(User).all()
# 先查詢所有user.
# 通過循環每一user對象, 再通過 backref 中的articles,反向查Article表中title
for row in user_list:
# print(row.__dict__)
for row2 in row.articles:
print(row.username,row2.title)
6.3.更新數據
# 查詢到作者對象
user_obj = db.session.query(User).filter(User.username == "xu").first()
# 查詢用戶對象id 與 Article外鍵id 關聯所有文章對象,並更新title
db.session.query(Article).filter(Article.author_id == user_obj.id).update({"title":"vue基礎"})
db.session.commit()
6.4刪除數據
# 刪除 作者名為xu的文章
user_obj = db.session.query(User).filter(User.username=="xu").first()
db.session.query(Article).filter(Article.author_id == user_obj.id).delete()
db.session.commit()
7.多對多關系
7.1基於relationship增加數據
# 通過 添加文章,再添加標簽
# 首先新建Article對象,
article_obj = Article(title="Go基礎",content="go語言指針。。。")
# 添加標簽對象。tags為Article表中backref用於關聯Tag表多對多關系
article_obj.tags = [Tag(name="編譯型語言"),Tag(name="支持協程"),Tag(name="非常快")]
db.session.add(article_obj)
# 提交數據
db.session.commit()
# 關閉連接
db.session.close()
7.2基於relationship查詢數據
# 查詢所有書籍和其標簽
article_obj = db.session.query(Article).all()
# 遍歷循環文章
for row in article_obj:
# 遍歷循環每個文章tag:
for row2 in row.tags:
# 打印title,name
print(row.title,row2.name)
# 通過tag標簽查詢所有文章
# 查詢所有tag標簽
tag_obj = db.session.query(Tag).all()
# 遍歷循環標簽
for row in tag_obj:
# 通過每個標簽對象.tags (注意此時tags為Article中字段名)
#(此字段通過relationship,關聯Tag表)
for row2 in row.tags:
# 打印tag的名字和文章title
print(row.name,row2.title)
7.3刪除數據
# 查詢 title為Go基礎的對象
article_obj = Article.query.filter(Article.title =="Go基礎").first()
# 查詢 tag為非常快的對象
tag = Tag.query.filter(Tag.name == "非常快").first()
# 通過文章對象.tags (tags通過relationship與Tag表建立關系)
article_obj.tags.remove(tag)
db.session.commit()
# 級聯刪除
# 查詢到 title為 Go基礎 文章
article_obj = Article.query.filter(Article.title =="Go基礎").first()
# 連表查詢到所關聯所有tags
tags = Tag.query.join(article_tag_table).join(Article).filter(Article.title =="Go基礎").all()
for t in tags:
# 遍歷循環tag標簽,逐個刪除 title為Go基礎 的對象
article_obj.tags.remove(t)
#最后刪除 title為 Go基礎 文章對象
db.session.delete(article_obj)
db.session.commit()
# 關閉連接
db.session.close()