資料庫與flask

Steven Wang
4 min readNov 7, 2020

--

學習用SQLite 部署用MySQL (MySQL比較麻煩)

SQLite是小型文檔型的資料庫,支持SQL

ORM 介面可以串接任一種SQL的底層(代碼與底層數據庫的選擇無關 都可以用 需要一個object relational mapper(ORM)工具)

安裝

for flask SQLAlchemy ORM (課程)

pip install flask_sqlalchemy

pip install Flask-Migrate

創建資料庫(SQL command)

1.進入MySQL

terminal> mysql -u loot -p
輸入密碼

2.創建資料庫

mysql> create database tradingdesk(dbname);

3.使用資料庫

mysql>use tradingdesk;

4,創建資料庫

create table user (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(64) NOT NULL UNIQUE,passqord_hash VARCHAR(128) NOT NULL,email VARCHAR(64) NOT NULL);

5.顯示資料庫結構

desc user;

6.新增資料

insert into user(username,password_hash,email) values (“admin”,MD5(‘admin’),”admin@admin.com”);

7.顯示資料

select * from user;

SQL Alchemy 初始化

(教學用SQLite 部署用MySQL 但程式碼都可以用)

db=init_app(app)需要設置 app.con fig[‘SQLALCHEMY_DATABASE_URI’]

SQL Alchemy [user] table的實現

創建user table SQLAchemy的物件

  1. 建立models.py的文件
    引入db
    建立Class級別的物件User

並建立__repr__函數 方便顯示內容

2. 檢查
terminal進入python
%python3

>>>from twittor.models import User
>>>user = User(username=’admin’, email=’admin@admin.cin’,password_hash=’ededededede’)
>>>user
id=None, username=admin, email=admin@admin.cin,password, password_hashededededede

3.使用定義過的class user 去做資料庫的Migrate
所謂的Migration 是Class table 映射到實體資料庫中
並能對資料庫版本做維護

通過User代碼定義出User資料庫
並真正的將table表映射出來

先設置 使用Migration 的先行設定

要使用其db command

設定manager.py 使用Flask-Script(Using Flask-Script)
可以下命令列

後續並關掉警告訊息
app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False

4.修改一下 讓app知道有這個 User Class Model

route.py / from twittor.models import User 在route.py
(引入讓app知道User Model)

init.py / form twittor.route import index, login
model.py / import db
所以在 init.py / form twittor.route import index, login時,就會呼叫route.py / from twittor.models import User,就會呼叫models.py/from twittor import db

db在__init__.py未實體化會出錯
因為順序實體化在後面 db = SQLAlchemy()

分階段的說
A.在route內import User (User Class在models內) app才會認識User Model
B.__init__內import route(牽涉models)
C.models內import db )(但db在__init__內還沒實體化,app還不知道db是什麼)

開始B的時候
import route 就A要先models import User
但是db還沒初始化
models User import db會出錯

改變執行順序db先實體化
再import route
才不會出錯

[這個浪費我些時間]
manage.py 與 manager.py,manager.py才是正確的

資料庫Migrate

5.開始Migrate command

5–1.初始化一個folder
python manager.py db init
生成migrations folder

5–2.migrate
python manager.py db migrate -m “create user” (-m message)

5–3.當前數據庫版本
python manager.py db current

5–4.migrate upgrade/downgrade (sqlite不支援drop刪除column這件事,但是MySQL支援 (替代方式用 刪除tradingdesk.db and 刪除migrations folder)

python manager.py db upgrade

python manager.py db downgrade(回到上一個版本)

如果是用MySQL 需先準備好MySQL Server / pip install pymysql
修改SQLALCHEMY_DATABASE_URI

pip install pymysql app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql:///root:root@localhost:3306/資料庫名稱'

sqlite 不支援只好刪除 migrations folder and database.db 重新執行上面命令(檔案管理員內執行)

6.新增關聯資料表

關聯資料表的意思是關聯存在的資料,例如欄位不能新增沒有在關聯資料表內的項目
透過db.ForeignKey(‘user.id’)去關聯資料user.id

user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
tweets = db.relationship('Tweet', backref = 'author' ,lazy = 'dynamic')

這是一個訪問的方法,Tweet為class Tweet

lazy 這個用到的時候再解釋

create_time = db.Column(db.DateTime, default=datetime.utcnow)

以上這個先pip install datetime

default 預設值

user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

used_id 欄位 需輸入user資料表有的id 才可以 user.id

重新執行5–1~5–4

把配置單獨拿出來

7.做更容易擴展程式的些改 config.py
單獨一個config.py文件,做集中化的管理
不是在__init__.py/create_app之中
把配置單獨拿出來

在config.py定義class config
定義一些class 級別的變量

如何使用config.py
在__init__.py / from twittor.config import Config

app.config.from_object(Config)

7–1.os絕對位置

sqlite:///:tradingdesk.db 這個是資料庫[相對位置]的目錄,絕對位置每台電腦不一樣,使用上會出問題

解決方式用os,取得config.py當前的路徑

import os
config_path = os.path.abspath(os.path.dirname(__file__))
__file__當前文件(指自己)

os.path.abspath絕對路徑
os.path.dirname(__file__)當前文件file的名字 (當前文件是config)
os.path.abspath(os.path.dirname(__file__))當前文件名字的絕對路逕

os.path.join( path, filename)

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(config_path, 'tradingdesk.db')

由於這個方式寫死DB及路徑,若是希望很方便的去修改,能透過環境變數的方式 os.environ.get(“”,””)

SQLALCHEMY_DATABASE_URI = os.environ.get(“DATABASE_URL”, “sqlite:///” + os.path.join(config_path, “tradingdesk.db”))

之後就可以非常方便的變更database的url
兩個改變的方式如下

1.export設置環境變量
export DATABASE_URL = ‘sqlite:///User/test.db’

2. 運行的時候設置環境變量
DATABASE_URL = ‘sqlite:///User/test.db’ python

刪除migrations folder 刪除.db 重新執行5–1~5–4

命令列數據庫操作

8 進入python

>>>from twittor import db, create_app
>>>app = craete_app()
>>>db
沒有內容沒有engine 是因為app沒有進入app context內

>>>app.app_context().push() 進入app context內
>>>db

有了engine 可以開始操作command

from twittor,models import User, Tweet 引入User Tweet Model
u = User(username=”admin”, email=”admin@admin.com”) 初始化一個Use實例
t = Tweet(body=’’this is first one”, user_id=2)
db.session.add(u) ‘新增
db.session.commit()

User.query.all() ‘查詢

User.query.get(1) ‘查詢id=1

刪除數據,要先知道要刪哪一條
t=Tweet.query.get(1)
db.session.delete(t) ‘刪除
db.session.commit()

更新修改
u=User.query.get(2)
u.email=”test1_new@admin.com”
db.session.commit()

多筆清除範例

tweets = Tweet.query.all()
for t in tweets:
db.session.delete(t)

users = User.query.all()
for u in users:
db.session.delete(u)

db.session.commit()

參考操作文件

其他選取方式範例

User.query.filter_by(username='peter').first()
User.query.order_by(User.username).all()
User.query.limit(1).all()

--

--

Steven Wang
Steven Wang

No responses yet