Flask(六) 數據庫操作SQLAlchemy

文章目錄

  • 一、準備工作
  • 二、最小化可運行示例
    • ? 補充
      • 延遲綁定方式(推薦方式)
  • 三、數據庫基本操作(增刪改查)
    • 1. 插入數據(增)
    • 2. 查詢數據(查)
    • 3. 更新數據(改)
    • 4. 刪除數據(刪)
  • 四、其他有用方法
  • 五、常用字段類型
  • 六、初始化數據庫腳本(推薦)
  • sqlalchemy 實例
    • 基本使用
    • 常見方法速查
    • 多表查詢(JOIN)
    • 原始 SQL 語句(可選)
    • 示例:分頁 + 排序
    • 推薦:使用 Flask-SQLAlchemy 提供的簡寫風格
  • 完整的 Flask-SQLAlchemy 配置示例(含連接池/超時/調試配置)
    • ? 1. config.py 配置文件
    • ? 2. app.py 應用初始化
    • ? 3. models.py 數據模型定義
    • ? 4. init_db.py 數據庫初始化腳本
  • 使用 PyMySQL 連接 MySQL,app.py 文件代碼:

  • 使用 SQLAlchemy:定義模型,配置數據庫,執行基本的 CRUD 操作。
  • 創建和管理數據庫:使用 db.create_all() 創建表。
  • CRUD 操作:添加、讀取、更新和刪除記錄。
  • 查詢操作:執行基本和復雜查詢,包括排序和分頁。
  • Flask-Migrate:使用 Flask-Migrate 管理數據庫遷移。
  • 執行原始 SQL:使用原始 SQL 語句進行數據庫操作

一、準備工作

pip install flask flask_sqlalchemy

二、最小化可運行示例

from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydb.sqlite3'
#或者
#app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:password@localhost/db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)# 定義數據模型(表)
class User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True, nullable=False)age = db.Column(db.Integer)# 創建表
with app.app_context():db.create_all()# 啟動應用
@app.route('/')
def index():return '數據庫已初始化'
部分含義
'sqlite:///mydatabase.db'使用 SQLite 數據庫,數據庫文件保存在當前目錄
SQLAlchemy(app)綁定 Flask 應用,初始化 ORM 引擎。也就是將 Flask 應用對象 app 注冊到 SQLAlchemy 對象中,從而啟用數據庫功能。
SQLALCHEMY_TRACK_MODIFICATIONS關閉事件監聽,提升性能,防止警告

? 補充

延遲綁定方式(推薦方式)

適用于大型項目或避免循環引用:

# extensions.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() # 先不綁定 app# app.py
from flask import Flask
from extensions import dbdef create_app():app = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydatabase.db'db.init_app(app) # ? 后綁定 appreturn app
寫法含義
db = SQLAlchemy(app)初始化并立刻綁定 app
db = SQLAlchemy() + db.init_app(app)更靈活,推薦在大型項目或工廠模式中使用

三、數據庫基本操作(增刪改查)

1. 插入數據(增)

with app.app_context():user = User(username='alice', age=20)db.session.add(user)db.session.commit()

db.session.add(user):將新用戶對象添加到會話中。
db.session.commit():提交事務,將更改保存到數據庫。

2. 查詢數據(查)

# 查詢所有
User.query.all()# 查詢第一條
User.query.first()# 條件查詢
User.query.filter_by(username='alice').first()# 更復雜的篩選
User.query.filter(User.age >= 18).all()

User.query.all():查詢所有用戶記錄。

User.query.all()時報錯,RuntimeError: Working outside of application context.
說明你試圖在沒有 Flask 應用上下文的環境中訪問數據庫。這是 Flask-SQLAlchemy 的一個常規限制。

正確解決方案:
示例1、直接加上 app.app_context()

import Userwith app.app_context():users = User.query.all()print(users) 

示例2、在 Python 交互模式中(REPL 或 Jupyter Notebook)

from your_project import app from your_project.models import
Userapp.app_context().push()  # 手動推入應用上下文 User.query.all()

示例 3:在 Flask 視圖函數中(上下文自動存在)

 @app.route("/users") def get_users():users = User.query.all()return jsonify([u.to_dict() for u in users]) 

🔍 為什么必須有應用上下文?
Flask-SQLAlchemy 底層依賴 current_app 和 g,這些變量必須在上下文中才存在

📌如果你使用的是“應用工廠模式”(create_app()),記得這樣寫:

app = create_app() with app.app_context():db.create_all()User.query.all() 

3. 更新數據(改)

with app.app_context():user = User.query.filter_by(username='alice').first()if user:user.age = 25db.session.commit()
@app.route('/update_user/<int:user_id>')
def update_user(user_id):user = User.query.get(user_id)if user:user.username = 'new_username'db.session.commit()return 'User updated!'return 'User not found!'

User.query.get(user_id):通過主鍵查詢單個用戶記錄。
更新字段值并提交事務。

4. 刪除數據(刪)

with app.app_context():user = User.query.filter_by(username='alice').first()if user:db.session.delete(user)db.session.commit()

db.session.delete(user):刪除用戶記錄,并提交事務。

四、其他有用方法

方法 / 類功能
db.Model所有模型基類
db.Column定義字段類型
db.session.add(obj)添加記錄
db.session.commit()提交更改
User.query.filter(...)ORM 查詢
db.create_all()創建所有表
db.drop_all()刪除所有表

五、常用字段類型

類型含義
db.String(n)字符串(最長 n)
db.Integer整數
db.Boolean布爾值
db.DateTime時間戳
db.Float浮點數

六、初始化數據庫腳本(推薦)

可以加一個 Python 腳本 init_db.py,自動初始化數據庫:

from app import db
from app import app  # 確保 Flask app 存在with app.app_context():db.create_all()print("數據庫已初始化!")

db.create_all():創建所有在當前上下文中定義的模型對應的表。

sqlalchemy 實例

基本使用

假設你有模型:

class User(db.Model):__tablename__ = 'users'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True)

? __tablename__ = "users"在 SQLAlchemy 中,這是在 ORM 模型類中定義 對應的數據庫表名。
? 不加 __tablename__ 會怎樣?
SQLAlchemy 默認使用類名的小寫作為表名,如 User → user
但不推薦依賴默認行為 —— 明確指定更安全、更清晰
模型是數據庫表的 Python 類,每個模型類代表數據庫中的一張表。
? 推薦命名風格

模型類名表名建議寫法
Userusers__tablename__ = "users"
Orderorders__tablename__ = "orders"
UserOrderuser_orders__tablename__ = "user_orders"

你可以:

# 查詢所有用戶
users = db.session.query(User).all()# 查詢用戶名為 'root' 的用戶
user = db.session.query(User).filter_by(username='root').first()# 查詢 ID 大于 10 的用戶
users = db.session.query(User).filter(User.id > 10).all()

常見方法速查

方法說明
query(Model)創建查詢對象
.filter(condition)過濾條件,支持表達式
.filter_by(field=value)簡寫形式,等同于 == 比較
.first()獲取第一條記錄或 None
.all()獲取所有結果(列表)
.count()獲取記錄數量
.limit(n)限制返回數量
.offset(n)跳過前 n 行記錄
.order_by(Model.field)排序(可加 .desc()
.one() / .one_or_none()獲取一條記錄(不唯一會報錯)
.distinct()去重

多表查詢(JOIN)

db.session.query(User, Post).join(Post, User.id == Post.user_id).all()
from sqlalchemy import or_users = User.query.filter(or_(User.username == 'john_doe', User.email == 'john@example.com')).all()

or_():用于執行復雜的查詢條件。

原始 SQL 語句(可選)

from sqlalchemy import text
db.session.execute(text("SELECT * FROM users WHERE id = :id"), {"id": 1}).fetchall()

db.session.execute():執行原始 SQL 查詢。

示例:分頁 + 排序

users = db.session.query(User) \.filter(User.username.like('%admin%')) \.order_by(User.id.desc()) \.offset(0).limit(10) \.all()

order_by():按指定字段排序。
paginate():分頁查詢。

推薦:使用 Flask-SQLAlchemy 提供的簡寫風格

User.query.filter_by(username='root').first()
User.query.filter(User.id > 10).all()

完整的 Flask-SQLAlchemy 配置示例(含連接池/超時/調試配置)

推薦項目結構(簡化)

your_project/
├── app.py
├── config.py           ← 配置集中管理
├── models.py           ← 數據模型
└── init_db.py          ← 初始化數據庫

? 1. config.py 配置文件

import osclass Config:# ? 數據庫連接(選你要的數據庫)# SQLite(開發測試用)SQLALCHEMY_DATABASE_URI = 'sqlite:///mydb.sqlite3'# MySQL 示例# SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://user:password@localhost:3306/mydb?charset=utf8mb4'# PostgreSQL 示例# SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://user:password@localhost/mydb'# ? SQLAlchemy 設置SQLALCHEMY_TRACK_MODIFICATIONS = False# ? 調試設置DEBUG = True# ? 數據庫連接池設置SQLALCHEMY_ENGINE_OPTIONS = {"pool_size": 10,            # 最大連接數"max_overflow": 5,          # 超出 pool_size 后允許的連接數"pool_timeout": 30,         # 獲取連接最大等待時間(秒)"pool_recycle": 1800,       # 自動重連時間(秒)防止 MySQL 8 小時斷開"echo": True,               # 輸出執行 SQL(調試用)}# ? 密鑰(如啟用 Session)SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key')

數據庫連接池說明(MySQL/PostgreSQL 推薦)

參數含義
pool_size最大連接數
max_overflow超出最大連接數后的額外連接數
pool_timeout獲取連接等待時長(秒)
pool_recycle多久重置連接(避免斷線),MySQL 默認 8 小時(28800 秒)斷連接,推薦 pool_recycle = 1800。
echo是否打印 SQL(調試用)

? 2. app.py 應用初始化

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Configdb = SQLAlchemy()def create_app():app = Flask(__name__)app.config.from_object(Config)db.init_app(app)# 注冊路由/藍圖@app.route('/')def index():return 'Hello Flask + SQLAlchemy'return app

? 3. models.py 數據模型定義

from app import dbclass User(db.Model):__tablename__ = 'users'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, nullable=False)age = db.Column(db.Integer)

? 4. init_db.py 數據庫初始化腳本

from app import create_app, db
from models import *app = create_app()with app.app_context():db.create_all()print("? 數據庫已初始化")

運行方式:

python init_db.py

使用 PyMySQL 連接 MySQL,app.py 文件代碼:

from flask import Flask, request, jsonify
import pymysqlapp = Flask(__name__)def get_db_connection():connection = pymysql.connect(host='localhost',user='username',password='password',database='dbname',cursorclass=pymysql.cursors.DictCursor)return connection@app.route('/add_user', methods=['POST'])
def add_user():data = request.jsonname = data['name']email = data['email']connection = get_db_connection()with connection.cursor() as cursor:cursor.execute('INSERT INTO user (username, email) VALUES (%s, %s)', (name, email))connection.commit()connection.close()return 'User added!'@app.route('/get_users')
def get_users():connection = get_db_connection()with connection.cursor() as cursor:cursor.execute('SELECT * FROM user')users = cursor.fetchall()connection.close()return jsonify(users)if __name__ == '__main__':app.run(debug=True)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912259.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912259.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912259.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PYTHON從入門到實踐7-獲取用戶輸入與while循環

# 【1】獲取用戶輸入 # 【2】python數據類型的轉換 input_res input("請輸入一個數字\n") if int(input_res) % 10 0:print("你輸入的數是10的倍數") else:print("你輸入的數不是10的倍數") # 【3】while循環&#xff0c;適合不知道循環多少次…

學習筆記(C++篇)—— Day 8

1.STL簡介 STL(standard template libaray-標準模板庫)&#xff1a;是C標準庫的重要組成部分&#xff0c;不僅是一個可復用的組件庫&#xff0c;而且是一個包羅數據結構與算法的軟件框架。 2.STL的六大組件 先這樣&#xff0c;下一部分是string的內容&#xff0c;內容比較多&a…

ant+Jmeter+jenkins接口自動化,如何實現把執行失敗的接口信息單獨發郵件?

B站講的最好的自動化測試教程&#xff0c;工具框架附項目實戰一套速通&#xff0c;零基礎完全輕松掌握&#xff01;自動化測試課程、web/app/接口 實現AntJMeterJenkins接口自動化失敗接口郵件通知方案 要實現只發送執行失敗的接口信息郵件通知&#xff0c;可以通過以下步驟實…

惡意Python包“psslib“實施拼寫錯誤攻擊,可強制關閉Windows系統

Socket威脅研究團隊發現一個名為psslib的惡意Python包&#xff0c;該軟件包偽裝成提供密碼安全功能&#xff0c;實則會突然關閉Windows系統。這個由化名umaraq的威脅行為者開發的軟件包&#xff0c;是對知名密碼哈希工具庫passlib的拼寫錯誤仿冒&#xff08;typosquatting&…

云原生灰度方案對比:服務網格灰度(Istio ) 與 K8s Ingress 灰度(Nginx Ingress )

服務網格灰度與 Kubernetes Ingress 灰度是云原生環境下兩種主流的灰度發布方案&#xff0c;它們在架構定位、實現方式和適用場景上存在顯著差異。以下從多個維度對比分析&#xff0c;并給出選型建議&#xff1a; 一、核心區別對比 維度服務網格灰度&#xff08;以 Istio 為例…

科技如何影響我們的生活?

科技已成為我們生活中不可或缺的一部分&#xff0c;徹底改變了我們工作、溝通和生活的方式。從智能手機到智能家居&#xff0c;科技已滲透到我們生活的每個角落。無論是用手機鬧鐘開啟新的一天&#xff0c;通過 Alexa 開關燈光&#xff0c;還是打開 Uber 或 Lyft 打車上班&…

Re--攻防世界-基礎android

Jadx 可以看到有賬號密碼輸入 進入checkPassword函數 分析一下&#xff1a; 對每個字符 pass[len] 進行以下計算 pass[len] (char) (((255 - len) - 100) - pass[len]); 解密腳本 def decrypt_password(): password [] for len in range(12): c (255 - le…

InnoDB表空間結構-系統表空間

系統表空間整體結構 頁號為7的SYS類型頁結構

如何構建知識庫

構建個人知識庫是一個系統化的過程&#xff0c;需要結合工具選擇、信息管理和持續優化。以下是分步驟的實用指南&#xff0c;包含現代工具和方法的建議&#xff1a; 一、明確知識庫定位&#xff08;Why&#xff09; ?核心目標? 學習型&#xff1a;支持學術研究/職業發展&…

3 大語言模型預訓練數據-3.2 數據處理-3.2.2 冗余去除——2.SimHash算法文本去重實戰案例:新聞文章去重場景

SimHash算法文本去重實戰案例&#xff1a;新聞文章去重場景 一、案例背景與目標二、具體實現步驟與示例1. **待去重文本示例**2. **步驟1&#xff1a;文本預處理與特征提取**3. **步驟2&#xff1a;特征向量化與哈希映射**4. **步驟3&#xff1a;特征向量聚合**5. **步驟4&…

MSPM0G3507之GPIO配置報錯 #Sysconfig報錯

聲明&#xff1a;本文完全免費閱讀&#xff0c;如果你發現某天文章被設置了“VIP權限”&#xff0c;請私信我解除&#xff08;非筆者所為&#xff09;。 一、問題現象 在打開sysconfig后&#xff0c;GPIO這里會報錯。 Unable to render selection Error:launchPadShortcut:Vali…

2025年檢測相機十大品牌測評:工業級精度與場景化解決方案解析

一、引言 在工業自動化與智能制造領域&#xff0c;檢測相機作為質量管控的核心硬件&#xff0c;正以“高精度、高速度、高適應性”的特性重塑生產流程。這類設備通過光學成像與智能算法結合&#xff0c;實現對工件表面缺陷、尺寸偏差、裝配精度的精準檢測&#xff0c;效率較傳…

Python異步編程深度解析

一、異步編程范式演進 同步阻塞的困境&#xff1a;GIL限制與線程切換開銷 事件循環本質&#xff1a;單線程并發模型 協程優勢&#xff1a;比線程更輕量的執行單元 IO密集型場景&#xff1a;網絡請求/文件操作的最佳實踐 二、核心語法精要 import asyncioasync def fetch_…

網絡緩沖區

用戶態網絡緩沖區 網絡緩沖區原理為什么需要用戶態網絡緩沖區Linux下如何接收和發送數據包用戶態網絡緩沖區設計的本質 網絡緩沖區代碼實現 網絡緩沖區原理 為什么需要用戶態網絡緩沖區 在網絡開發中&#xff0c;我們經常使用到read/write/recv/send等系統調用接口&#xff0…

微信小程序實現簡版點贊動畫

這是第二次寫canvas&#xff0c;基于微信小程序文檔demo進行改寫 demo效果為方塊橫向來回循環移動 我想做的是直播間那種點贊效果&#xff0c;豎向曲線移動、方塊換成圖片、點擊添加繪制元素 第一階段實現豎向曲線移動、點擊添加繪制元素&#xff1b;下一階段講方塊替換為圖…

實現一個AI大模型當前都無法正確實現的基礎二叉樹讀取算法

概述 圖1: 圖2: 上圖幫大家溫習完全二叉樹的概念&#xff0c;本文講的是完全順序二叉樹的初始化 華為的員工、考過華為OD的員工、參加過其他類似大廠的考試的員工一般做過二叉樹的初始化&#xff0c;甚至有些還碰到過手撕代碼時面試官要求做二叉樹遍歷&#xff0c;看完本文的…

【攻防篇】阿里云服務器中 如何關閉docker api端口

在阿里云服務器&#xff08;ECS&#xff09;上&#xff0c;Docker API 默認監聽 2375&#xff08;非加密&#xff09;和 2376&#xff08;TLS加密&#xff09;端口。如果未正確配置&#xff0c;可能被惡意利用&#xff08;如挖礦攻擊&#xff09;。以下是關閉和加固 Docker API…

暑假復習篇之類與對象

面向對象&#xff1a;①類與對象②封裝③繼承④接口 類與對象&#xff1a; 概念&#xff1a;類就是類別的意思 用class表示 / 面向對象編程&#xff0c;萬物皆可編程&#xff0c;在程序中表示一個事物時&#xff0c;往往因為事物的復雜程度導致編程的代碼非常復雜 【基本數…

RabbitMQ RPC模式Python示例

文章目錄 1.服務端2.客戶端3.調用結果 1.服務端 #!/usr/bin/env python3 # -*- coding: UTF-8 -*- """ File: rabbitmq_server.py Date: 2025/6/26 10:42 Author: xxx Description: 1. RabbitMQ服務端&#xff0c;支持多節點命令執行 2. 作為被控…

Rust代碼規范之蛇形命名法和駝峰命名法

Rust 使用兩種主要的命名風格&#xff1a;駝峰命名法&#xff08;UpperCamelCase&#xff09;和蛇形命名法&#xff08;snake_case&#xff09;。通常&#xff0c;類型&#xff08;如結構體、枚舉、特征&#xff09;使用駝峰命名法&#xff0c;而變量、函數、方法等使用蛇形命名…