flask操作資料庫 準備工作 安裝flask-script(版本過高可能會報錯) pip install flask-script==2.0.3 使用flask-script里的Manager類實例化來管理項目的啟動等 from apps import create_app from flask_ ...
flask操作資料庫
準備工作
- 安裝flask-script(版本過高可能會報錯)
pip install flask-script==2.0.3
使用flask-script里的Manager類實例化來管理項目的啟動等
from apps import create_app
from flask_script import Manager
app = create_app()
manager = Manager(app=app)
if __name__ == '__main__':
# 運行app模塊
manager.run()
在啟動項目時由原來的python app.py 改成了python app.py runserver
- 安裝pymysql
pip install pymysql
- 安裝flask-sqlalchemy
pip install flask-sqlalchemy
- 安裝flask-migrate,版本過高可能出現問題
pip install flask-migrate==2.7.0
配置資料庫
- 在settings里配置一下資料庫連接路徑
class DevelopmentConfig:
ENV = 'development' # 設置環境為開發環境
DEBUG = True # 設置debug為true
SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:[email protected]:3306/flaskday05'#訪問的資料庫+用的驅動://資料庫的用戶名:密碼@伺服器地址:埠號/資料庫
# 設置sqlalchemy不自動更跟蹤資料庫
SQLALCHEMY_TRACK_MODIFICATIONS=False
SQLALCHEMY_ECHO=True#調試模式
- 在項目文件下新建一個ext包,在包的init文件內建立映射對象
# 創建一個映射對象
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
- 創建完之後,需要將映射對象與app進行關聯,在apps包的init文件內進行關聯
# 將db(orm映射)對象和app進行關聯
db.init_app(app)
- flask-migrate是一個為Flask應用處理SQLAlchemy資料庫遷移的擴展,使得可以通過Flask的命令行介面或者Flask-Scripts對資料庫進行操作。
#在app.py文件中,當創建完app對象之後
from flask_migrate import Migrate, MigrateCommand
migrate=Migrate(app=app,db=db)#建立app影響資料庫的映射
manager.add_command('db',MigrateCommand)#將命令交給manager管理
- 在各藍圖中創建模型(類)時,要用到db的model
#在model.py文件中
from exts import db
class User(db.Model):
- 模型的基礎創建格式和欄位類型
- 將創建好的模型(自定義的類)導入到app.py文件中
from apps.user.models import User
- 使用terminal運行flask項目
初始化(一個項目只需要初始化一次,用來生成migrations文件夾)python app.py db init
更新版本(每次修改後要運行,用來在versions文件中生成最新的版本py文件)python app.py db migrate
資料庫同步(每次修改要運行,用來將最新版本的內容更新到資料庫上)python app.py db upgrade
刪除時:python app.py db downgrate 降級並刪除版本文件
往資料庫插入數據
每次插入單挑數據
一次性插入多條數據
# 一次性插入多條數據
user1 = User(name='wang',email='[email protected]',pswd='123456',role_id=role1.id)
user2 = User(name='zhang',email='[email protected]',pswd='201512',role_id=role2.id)
user3 = User(name='chen',email='[email protected]',pswd='987654',role_id=role2.id)
user4 = User(name='zhou',email='[email protected]',pswd='456789',role_id=role1.id)
db.session.add_all([user1,user2,user3,user4])
db.session.commit()
查詢資料庫
- filter模糊查詢,返回名字結尾字元為g的所有數據。
User.query.filter(User.name.endswith('g')).all()
查詢結果為:列表裡套著對象
[<User 1>, <User 2>]
- 查詢:filter_by精確查詢
返回名字等於wang的所有user
User.query.filter_by(name='wang').all()
後面加.first()返回查詢到的第一個對象
all()返回查詢到的所有對象
- get(),參數為主鍵,如果主鍵不存在沒有返回內容
User.query.get(2)
- 邏輯非,返回名字不等於wang的所有數據
User.query.filter(User.name!='wang').all()
- 邏輯或,需要導入or_
from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
- 邏輯與,需要導入and,返回and()條件滿足的所有數據
from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
- not_ 相當於取反
from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()
- 其他
- 排序order_by
- limit限制
刪除數據
user = User.query.first()
db.session.delete(user)
db.session.commit()
更新數據
user = User.query.first()
user.name = 'dong'
db.session.commit()
模型表直接的關聯
- 一對多
class Role(db.Model):
...
#關鍵代碼
user = db.relationship('User', backref='role', lazy='dynamic')
...
class User(db.Model):
...
role = db.Column(db.Integer, db.ForeignKey('roles.id'))
- 其中realtionship描述了Role和User的關係。在此文中,第一個參數為對應參照的類"User"
- 第二個參數backref表示當使用user對象反向查詢時,使用user.role查詢到role表中的數據
- 第三個參數lazy決定了什麼時候SQLALchemy從資料庫中載入外鍵模型數據
如果設置為子查詢方式(subquery),則會在載入完Role對象後,就立即載入與其關聯的對象,這樣會讓總查詢數量減少,但如果返回的條目數量很多,就會比較慢
設置為 subquery 的話,role.users 返回所有數據列表
另外,也可以設置為動態方式(dynamic),這樣關聯對象會在被使用的時候再進行載入,並且在返回前進行過濾,如果返回的對象數很多,或者未來會變得很多,那最好採用這種方式
設置為 dynamic 的話,role.users 返回查詢對象,並沒有做真正的查詢,可以利用查詢對象做其他邏輯,比如:先排序再返回結果
關聯查詢
角色和用戶的關係是一對多的關係,一個角色可以有多個用戶,一個用戶只能屬於一個角色。
- 查詢角色的所有用戶
#查詢roles表id為1的角色
ro1 = Role.query.get(1)
#查詢該角色的所有用戶
ro1.use.all()
- 查詢用戶所屬角色
#查詢users表id為3的用戶
us1 = User.query.get(3)
#查詢用戶屬於什麼角色
us1.role
- 多對多
需要定義一個中間表,包含兩個模型的外鍵欄位就可以了,並作為一個“複合主鍵”
在兩個需要做多對多的模型中隨便選擇一個模型,定義一個relationship屬性,來綁定三者之間的關係,在使用relationship的時候,需要傳入一個secondary=中間表模型名。
# 中間表,也可以重新定義一個類class,表示中間表
article_tag = 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)
title = db.Column(db.String(64))
tags = db.relationship('Tag', secondary=article_tag, backref=db.backref('articles'))
# 這裡需要指定一個參數secondary,值為中間表的表名
# 標簽表
class Tag(db.Model):
__tablename__ = 'tag'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
多對多關係的查詢
1.查詢文章所有的標簽:
article = Article.query.filter(Article.title=="xxx").first()
tags = article.tags
2.查詢一個標簽涉及的所有文章:
tag = Tag.query.get(2)
articles = tag.articles