python框架之Flask基礎篇(二)-------- 資料庫的操作

来源:https://www.cnblogs.com/RomanticLife/archive/2018/01/28/8372624.html
-Advertisement-
Play Games

1.flask連接資料庫的四步: app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = Fals ...


1.flask連接資料庫的四步:

  1. 倒入第三方資料庫擴展包:from flask_sqlalchemy import SQLAlchemy
  2. 配置config屬性,連接資料庫:

    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

  3. 創建資料庫first_flask
  4. 創建操作資料庫對象:db = SQLAlchemy(app)

下麵直接上代碼解釋:

 

# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# url的格式為:資料庫的協議://用戶名:密碼@ip地址:埠號(預設可以不寫)/資料庫名
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"
# 動態追蹤資料庫的修改. 性能不好. 且未來版本中會移除. 目前只是為瞭解決控制台的提示才寫的
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 創建資料庫的操作對象
db = SQLAlchemy(app)


class Role(db.Model):

    __tablename__ = "roles"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    # 給Role類創建一個uses屬性,關聯users表。
    # backref是反向的給User類創建一個role屬性,關聯roles表。這是flask特殊的屬性。
    users = db.relationship('User',backref="role")
    # 相當於__str__方法。
    def __repr__(self):
        return "Role: %s %s" % (self.id,self.name)


class User(db.Model):
    # 給表重新定義一個名稱,預設名稱是類名的小寫,比如該類預設的表名是user。
    __tablename__ = "users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    email = db.Column(db.String(32),unique=True)
    password = db.Column(db.String(16))
    # 創建一個外鍵,和django不一樣。flask需要指定具體的欄位創建外鍵,不能根據類名創建外鍵
    role_id = db.Column(db.Integer,db.ForeignKey("roles.id"))

    def __repr__(self):
        return "User: %s %s %s %s" % (self.id,self.name,self.password,self.role_id)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 刪除所有的表
    db.drop_all()
    # 創建表
    db.create_all()

    ro1 = Role(name = "admin")
    # 先將ro1對象添加到會話中,可以回滾。
    db.session.add(ro1)
    
    ro2 = Role()
    ro2.name = 'user'
    db.session.add(ro2)
    # 最後插入完數據一定要提交
    db.session.commit()

    us1 = User(name='wang', email='[email protected]', password='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='[email protected]', password='201512', role_id=ro2.id)
    us3 = User(name='chen', email='[email protected]', password='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='[email protected]', password='456789', role_id=ro1.id)
    us5 = User(name='tang', email='[email protected]', password='158104', role_id=ro2.id)
    us6 = User(name='wu', email='[email protected]', password='5623514', role_id=ro2.id)
    us7 = User(name='qian', email='[email protected]', password='1543567', role_id=ro1.id)
    us8 = User(name='liu', email='[email protected]', password='867322', role_id=ro1.id)
    us9 = User(name='li', email='[email protected]', password='4526342', role_id=ro2.id)
    us10 = User(name='sun', email='[email protected]', password='235523', role_id=ro2.id)
    db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
    db.session.commit()
    app.run(debug=True)

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下麵插播一條bug:

當把表格創建完成,註釋這兩句話:

 # 刪除所有的表
    db.drop_all()
    # 創建表
    db.create_all()

然後向表格裡面插入數據,此時會出現這樣的錯誤:

sqlalchemy.exc.IntegrityError: (_mysql_exceptions.IntegrityError) (1062, "Duplicate entry 'admin' for key 'name'") [SQL: u'INSERT INTO roles (name) VALUES (%s)'] [parameters: ('admin',)]

查了網上的好多資料說把欄位的約束unique=True去掉就好了,但是根本原因不在這。

原因就是因為app.run(debug=True)。開啟debug模式之後,當我們修改代碼的時候,比如將刪除表和創建表這兩句話註釋,然後打開插入數據的註釋。這個過程debug模式預設就已經把程式運行一遍了。此時資料庫就已經有了數據,當我們再次手動執行的時候,又往資料庫中插入了一條數據,這時候就會報錯。因為欄位的約束是唯一性的unique,所以解決的辦法有兩種:

第一種:就是不要將刪除表和創建表這兩句話註釋,每次執行都要帶著這兩個句話。無論是debug模式自動執行還是我們手動執行程式,都會先刪除表然後再創建表,所以執行多少次都不怕。

第二種:關閉debug模式。就是這樣app.run()

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.資料庫的增刪改查:

1.以下的方法都是返回一個新的查詢,需要配合執行器使用。

filter(): 過濾,功能比較強大。
filter_by():過濾,用在一些比較簡單的過濾場景。

order_by():排序。預設是升序,降序需要導包:from sqlalchemy import * 。然後引入desc方法。比如order_by(desc("email")).按照郵箱字母的降序排序。

 

group_by():分組。

2.以下都是一些常用的執行器:配合上面的過濾器使用。

get():獲得id等於幾的函數。比如:查詢id=1的對象。get(1)。切記:括弧里沒有“id=”,直接傳入id的數值就ok。因為該函數的功能就是查詢主鍵等於幾的對象。

all():查詢所有的數據。

first():查詢第一個數據。

count():返回查詢結果的數量。

paginate():分頁查詢,返回一個分頁對象。paginate(參數1,參數2,參數3)

參數1:當前是第幾頁,參數2:每頁顯示幾條記錄,參數3:是否要返回錯誤。

返回的分頁對象有三個屬性:items:獲得查詢的結果,pages:獲得一共有多少頁,page:獲得當前頁。

3.常用的邏輯符:

需要倒入包才能用的有:from sqlalchemy import * 

not_  and_  or_   還有上面說的排序desc。

常用的內置的有:in_      表示某個欄位在什麼範圍之中。

4.其他關係的一些資料庫查詢:

endswith():以什麼結尾。

startswith():以什麼開頭。

contains():包含

5.下麵體會一下上面的這些用法:

1. 查詢所有用戶數據
User.query.all()
2. 查詢有多少個用戶
User.query.count()
3. 查詢第1個用戶
User.query.first()

4. 查詢id為4的用戶[3種方式]
User.query.get(4)
User.query.filter_by(id=4).first()    
User.query.filter(User.id==4).first()

filter:(類名.屬性名==)
filter_by:(屬性名=)

filter_by: 用於查詢簡單的列名,不支持比較運算符
filter比filter_by的功能更強大,支持比較運算符,支持or_、in_等語法。


5. 查詢名字結尾字元為g的所有數據[開始/包含]
User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.name.contains('g')).all()

6. 查詢名字不等於wang的所有數據[2種方式]
 from sqlalchemy import not_
註意了啊:邏輯查詢的格式邏輯符_(類屬性其他的一些判斷) User.query.filter(not_(User.name
=='wang')).all() User.query.filter(User.name!='wang').all() 7. 查詢名字和郵箱都以 li 開頭的所有數據[2種方式] from sqlalchemy import and_ User.query.filter(and_(User.name.startswith('li'), User.email.startswith('li'))).all() User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all() 8. 查詢password是 `123456` 或者 `email` 以 `itheima.com` 結尾的所有數據 from sqlalchemy import or_ User.query.filter(or_(User.password=='123456', User.email.endswith('itheima.com'))).all() 9. 查詢id為 [1, 3, 5, 7, 9] 的用戶列表 User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all() 10. 查詢name為liu的角色數據 關係引用 User.query.filter_by(name='liu').first().role.name 11. 查詢所有用戶數據,並以郵箱排序 排序 User.query.order_by('email').all() 預設升序 User.query.order_by(desc('email')).all() 降序 12. 查詢第2頁的數據, 每頁只顯示3條數據 help(User.query.paginate) 三個參數: 1. 當前要查詢的頁數 2. 每頁的數量 3. 是否要返回錯誤 pages = User.query.paginate(2, 3, False) pages.items # 獲取查詢的結果 pages.pages # 總頁數 pages.page # 當前頁數

 3.使用第三方擴展框架遷移資料庫文件。

使用框架需要配置的代碼如下:

# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy  # 操作資料庫的擴展包
from flask_script import Manager  # 用命令操作的擴展包
from flask_migrate import Migrate,MigrateCommand  # 操作資料庫遷移文件的擴展包

app = Flask(__name__)
app.debug = True
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/second_flask"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)
manager = Manager(app)
# 創建遷移對象
migrate = Migrate(app,db)
# 將遷移文件的命令添加到‘db’中
manager.add_command('db',MigrateCommand)


class Role(db.Model):
    __tablename__ = "table_roles"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    info = db.Column(db.String(100))
    Users = db.relationship("User",backref='role')


class User(db.Model):
    __tablename__ = "table_users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    info = db.Column(db.String(200))
    role_id = db.Column(db.Integer,db.ForeignKey("table_roles.id"))




@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':

    manager.run()

 

使用遷移命令如下:

比如上面的代碼所在的文件名稱為database.py。

1.python database.py db init    生成管理遷移文件的migrations目錄

2.python database.py db migrate -m "註釋"   在migrations/versions中生成一個文件,該文件記錄數據表的創建和更新的不同版本的代碼。

3.python database.py db upgrade  在資料庫中生成對應的表格。

4.當需要改表格的時候,改完先執行第二步,然後再執行第三步。

5.需要修改數據表的版本號的時候需要做的操作如下:

python database.py db upgrade 版本號  向上修改版本號

python database.py db downgrade 版本號   向下修改版本號

可能用到的其他的語句:

python database.py db history    查看歷史版本號

python database.py db current   查看當前版本號

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • redis的使用和安裝,redis基礎和高級部分 在後端開發中,為了提高性能,對於一些經常查詢但是又不太變化的內容會使用redis,比如前端的列表展示項等,如果數據有變化也可以清空緩存,讓前端查一次資料庫,所以使用redis相對高效和靈活.本文主要對於redis在linux上的使用和安裝進行說明。 ...
  • jsp jsp簡介: JSP全名為Java Server Pages,中文名叫java伺服器頁面,其根本是一個簡化的Servlet設計,在jsp中既可以寫html 代碼 ,又可以寫java代碼 作用:將頁面顯示與業務邏輯相分離; 通常分為三部分: java 代碼 html代碼 jsp指令 jsp本質 ...
  • 1.flask特有的變數和函數: 變數:g、session、request、config 函數:url_for()、get_flashed_messages()這個函數註意了啊,記住這是個函數,別忘了寫括弧!!!!!!!!! 廢話不多說,直接上代碼體驗一下: 先解釋一個bug,當我們設置了# -*- ...
  • ——————————————————————————————————————————————————————————————————————————————————————————— 本篇開始進入正題,因為涉及 MDL,所以相關的背景知識是必須的: nt!_MDL 代表一個“記憶體描述符鏈表”結構,它 ...
  • a=0#回車 print(a)#回車 輸出0 #複製下麵這一段開始 def funcA(): b='A'def funcB(): a=2 b='B' print(a,b) def funcC(): nonlocal a b='C' a=3 print(a,b) ... ...
  • 這是測試 Hhhhhhhhhhhhhhh Aaaaaaaaaaaaa Gggggggggggggggg ...
  • 這是我的思路,應該屬於雙路快速排序的一種,快速排序的解決思路太多了,有單路、雙路、三路,每種的寫法也各有不同,每個人的思路都千奇百怪。 ...
  • 離散存儲[鏈表] 1.定義: n個節點離散分配,彼此通過指針相連 每個節點只有一個前驅節點 只有一個後續節點 首節點沒有前驅節點,尾節點沒有後續節點 2.專業術語: 首節點:第一個有效節點 尾節點:最後一個有效節點 頭結點:並不存放有效數據,方便操作,頭結點的數據類型和首節點類型一樣 頭指針:指向頭 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...