flask 更新數據庫 --


更新書庫庫表

模型類(表)不是一成不變的,當你添加了新的模型類,或是在模型類中添加了新的字段,甚至是修改了字段的名稱或類型,都需要更新表。在前面我們把數據庫表比成盛放貨物的貨架,這些貨架是固定生成的。當我們在操控程序(DBMS/ORM)變更了貨架的結構時,倉庫的貨架也要根據變化相應進行調整。而且,當貨架的結構產生變動時,我們還需要考慮如何處理貨架上的貨物(數據)。

當你在數據庫的模型中添加了一個新的字段后,比如在Note模型里添加了一個存儲筆記創建時間的timestamp字段。

class Note(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    timeStamp = db.Column(db.String(70), unique=True)
    body = db.Column(db.Text)
    def __repr__(self):
        # %r是用repr()方法處理對象,返回類型本身,而不進行類型轉化
        return '<Note %r>' % self.body
 

此時模型類的定義中,加入了一個新的列,在命令行界面初始化數據時,只給了body賦了值,此時訪問這個表的數據時,這條數據有一個字段沒有初始化,就是表的結構變化了,需要更新這個表結構,才能正常訪問。

 

這時在命令行里查看note表的字段時,會看到報錯:

>>> Note.query.all()
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: note.timeStamp
[SQL: SELECT note.id AS note_id, note."timeStamp" AS "note_timeStamp", note.body AS note_body
FROM note]

 

這段錯誤信息支出note表中沒有timestamp列,並在中括號里給出了查詢所對應的SQL原語,之所以會出錯,是因為數據庫並不會隨着模型的修改而自動更新。就像之前關於倉庫的比喻,倉庫里來了一批新類型的貨物,可我們還沒為他們安排響應的貨架,這當然要出湊了,下面學習如果更新數據庫。

重新生成表

重新調用create_all()方法並不會起到更新表或重新創建表的作用。如果你並不在意表中的數據,最簡單的方法是使用drop_all()方法刪除表以及其中的數據,然后再使用create_all()方法重新創建:

>>> db.drop_all()

>>> db.create_all()

這會清楚數據庫里的原有數據,請勿在生產環境下使用。

為了方便開發,我們修改initdb命令函數的內容,為其增加一個—drop選項來支持刪除表和數據庫后進行重建,如下所示:

app.py: 支持刪除表后重建

 

@app.cli.command()
@click.option('--drop', is_flag=True, help='Create after drop')
def initdb(drop):
    """Initialize the database."""
    if drop:
        click.confirm('This operation will delete the database, do you want to continue?', abort = True)
        db.drop_all()
        click.echo('Drop tables.')
    db.create_all()
    click.echo('Initialized database.')
 
        

在這個命令函數前,我們使用click提供的option裝飾器為命令添加了一個—drop選項,將is_flag參數設為True可以將這個選項聲明為布爾值標志(boolean flag)。--drop選項的值作為drop參數傳入命令函數,如果提供了這個選項,那么drop的值將是True,否則為False。因為添加—drop選項會直接清空數據庫內容,如果需要,也可以通過click.confirm()函數添加一個確認提示,這樣只有輸入y或yes才會繼續執行操作。

下面來用這個命令重建數據庫和表:

(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask initdb --drop
This operation will delete the database, do you want to continue? [y/N]: y
Drop tables.
Initialized database.

 

當使用SQLite時,直接刪除data.db文件和調用drop_all()方法效果相同,而且更直接,不容易出錯。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM