新手指南:Python 與 PostgreSQL 的強力橋樑——psycopg 驅動程式

更新日期: 2025 年 3 月 29 日

本文為 Django 連接 PostgreSQL 基學教學,第 1 篇

  1. 新手指南:Python 與 PostgreSQL 的強力橋樑——psycopg 驅動程式 👈 所在位置
  2. 新手指南:Django 與 PostgreSQL 的資料庫設定與密碼管理

在開發 Python 應用程式時,經常需要與資料庫互動,而 PostgreSQL 是一個功能強大的關係型資料庫管理系統。

為了讓 Python 能夠高效地與 PostgreSQL 資料庫進行溝通,我們需要一個專用的驅動程式——psycopg

本篇文章將帶您了解 psycopg 的基本概念、如何與 Django 整合,並提供實際操作範例,幫助您快速上手。


psycopg 是什麼?

概念簡介

psycopg 是 Python 與 PostgreSQL 互動的驅動程式,提供穩定且高效能的方式來連接和操作資料庫。

主要功能

  • 支援執行各類 SQL 查詢(如 SELECTINSERT)。
  • 支援 PostgreSQL 的進階功能,包括事務管理、JSON 資料類型、陣列操作和游標(Cursor)。
  • 適合多執行緒環境,為高效能應用程式提供支持。

目前最新版本為 psycopg3,它是 psycopg2 的升級版,支援更多現代化功能(如非同步操作)。


Django 與 PostgreSQL 的連接

Django 是一個高效能的 Python 網頁框架,內建 ORM(物件關聯映射),能讓開發者以 Python 語法操作資料庫。

Django 預設透過 psycopg 驅動程式與 PostgreSQL 進行連接。

安裝 psycopg 驅動程式

在您的開發環境中安裝 psycopg。可以選擇安裝 psycopg2 或更新的 psycopg3

# 安裝 psycopg2
pip install psycopg2

# 或安裝 psycopg3
pip install "psycopg[binary]"

配置 Django 的資料庫設定

在 Django 專案的 settings.py 文件中,設定 PostgreSQL 資料庫的連接資訊:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',  # 使用 PostgreSQL 驅動程式
        'NAME': 'your_database_name',              # 資料庫名稱
        'USER': 'your_database_user',              # 使用者名稱
        'PASSWORD': 'your_password',               # 密碼
        'HOST': 'localhost',                       # 資料庫伺服器位置
        'PORT': '5432',                            # 資料庫埠號(默認為 5432)
    }
}

測試連接

檢查 Django 是否成功連接到資料庫:

  1. 遷移資料庫結構
    執行以下命令,確保 Django 的內建資料表(如 auth_user)被正確建立: python manage.py migrate
  2. 啟動伺服器測試應用
    如果能正常啟動伺服器並運行,表示 Django 已成功連接到 PostgreSQL。

使用 ORM 操作資料庫

Django 的 ORM 提供高效的資料庫操作功能,以下是基本範例:

插入資料

from myapp.models import MyModel

# 插入一筆資料
MyModel.objects.create(name="Example", value=42)

查詢資料

# 查詢資料
records = MyModel.objects.filter(value=42)
print(records)

psycopg 的運作方式

當 Django 與 PostgreSQL 互動時,psycopg 作為核心驅動程式,負責處理從高層的 Django ORM 到低層資料庫之間的溝通。

以下是更詳細的解釋這個運作流程的幾個關鍵點:

選擇 PostgreSQL 引擎

  • 在 Django 的設定檔(settings.py)中,透過將 ENGINE 設定為 'django.db.backends.postgresql',指定要使用 PostgreSQL 作為資料庫後端。
  • 這時,Django 會自動使用 psycopg 作為 PostgreSQL 的 Python 驅動程式,因為它是官方推薦且與 Django 完美整合的套件。

Django ORM 的 SQL 語句生成

  • 當開發者在程式中執行 ORM 操作時(例如 Model.objects.filter()Model.objects.create()),Django ORM 負責將這些高階 Python 方法轉換成相應的 SQL 查詢語句。
  • 舉例來說:
# 假設有一個名為 Book 的模型
Book.objects.filter(title="Django")
  • Django ORM 會生成類似這樣的 SQL:
SELECT * FROM book WHERE title = 'Django';

透過 psycopg 與資料庫溝通

  • psycopg 在這個階段負責接收來自 Django 的 SQL 語句,並透過 PostgreSQL 的協議,將 SQL 傳送到資料庫伺服器執行。
  • 它處理低層次的通訊細節,例如:
    • 開啟連線(Connection)
    • 傳送查詢
    • 管理交易(Transaction,包含 COMMIT 或 ROLLBACK)
    • 傳遞參數化查詢以避免 SQL Injection(SQL 注入)。
    • 舉例:
cursor.execute("SELECT * FROM book WHERE title = %s", ["Django"])

這裡的 %s 是一種參數佔位符,psycopg 負責正確插入引數,確保安全性。

補充:什麼是「交易」?

在資料庫中,交易(Transaction) 是一組操作的集合,這些操作作為一個整體被執行。

這裡有兩個關鍵的原則:

  • 要麼全部成功,要麼全部失敗(All or nothing)。
  • 保證資料的一致性和完整性。

舉個簡單例子: 假設你在一個銀行系統中要進行「轉帳」操作:

  1. 從帳戶 A 減少 $100。
  2. 將 $100 增加到帳戶 B。

這兩個步驟應該被視為一個整體:

  • 如果第一步成功,但第二步失敗(例如系統崩潰),就會出現問題,帳戶 A 的錢被扣了,但帳戶 B 沒有收到,這會導致資料不一致。

透過交易,我們可以確保這兩步要麼都完成(成功),要麼都回滾(失敗)。

COMMIT 和 ROLLBACK 是什麼?

交易管理主要有兩個重要指令:

  • COMMIT:確認所有操作成功,將這些改變保存到資料庫。
  • ROLLBACK:如果某些操作出現問題,取消所有尚未保存的改變,資料庫恢復到操作前的狀態。
為什麼交易很重要?

交易確保資料庫操作的可靠性和一致性,特別是在多步驟操作中,防止資料庫進入不一致的狀態。

例如:

  • 電商系統:訂單生成、庫存扣減、付款確認需要統一處理。
  • 金融系統:處理轉帳、記錄歷史交易。
在 Django 和 psycopg 裡,交易怎麼運作?
  • 當你進行資料庫操作(如 save()update())時,Django 通常會自動管理交易。
  • 如果需要執行多個步驟且需要手動管理,Django 提供了 transaction.atomic() 工具,讓你能確保多個操作要麼一起成功,要麼一起失敗。
例子:銀行轉帳的交易流程

假設你寫了一段程式模擬轉帳操作:

from django.db import transaction

try:
    with transaction.atomic():  # 開啟一個交易
        # 減少帳戶 A 的餘額
        account_a.balance -= 100
        account_a.save()

        # 增加帳戶 B 的餘額
        account_b.balance += 100
        account_b.save()

        # 如果這裡一切成功,Django 會自動執行 COMMIT
except Exception as e:
    # 如果任何一個操作失敗,Django 會執行 ROLLBACK
    print("交易失敗!", e)
  • 如果 兩個步驟都成功
    • Django 會執行 COMMIT,將這些改變永久保存到資料庫中。
  • 如果 任何一個步驟失敗(例如帳戶 B 不存在):
    • Django 會執行 ROLLBACK,撤銷所有已經進行的操作(如還原帳戶 A 的餘額)。

以下用圖解來幫助理解交易流程:

1. 開始交易 (Transaction)
   ├── 減少帳戶 A 的餘額
   ├── 增加帳戶 B 的餘額
   ├── 檢查是否成功
       ├── 全部成功 -> COMMIT -> 資料保存到資料庫
       └── 失敗 -> ROLLBACK -> 資料回到最初狀態

延伸閱讀:關聯式資料庫與交易(Transaction)機制入門

補充:什麼是 SQL Injection(SQL 注入)?

SQL Injection 是一種常見的攻擊方式,攻擊者透過在輸入中,插入惡意的 SQL 語句來操控你的資料庫。

這種攻擊可能會:

  • 獲取敏感資料。
  • 刪除或修改資料庫中的內容。
  • 甚至完全摧毀資料庫。

舉例: 假設你有一個登入系統,使用者輸入帳號和密碼。後端程式執行類似這樣的查詢:

SELECT * FROM users WHERE username = 'user_input' AND password = 'user_password';

如果使用者的輸入如下:

  • username: admin
  • password: ' OR '1'='1

這時,生成的 SQL 會變成:

SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';

這條語句總是成立,因為 1='1' 永遠為真。攻擊者因此可以繞過登入檢查,取得未經授權的存取。

什麼是參數化查詢?

參數化查詢 是一種安全的處理方式,可以避免 SQL Injection。

它的核心是:

  • 將使用者輸入的資料和 SQL 語句分開處理。
  • 使用佔位符(placeholder)來插入參數,讓資料庫將參數視為純資料而非 SQL 指令。
怎麼用參數化查詢避免 SQL Injection?

在 Django 中,透過 psycopg 驅動程式,參數化查詢可以輕鬆實現。

例子: 我們有一個查詢要檢查使用者的帳號和密碼:

不安全的方式(容易被注入攻擊)
username = "admin"
password = "' OR '1'='1"
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}';"
cursor.execute(query)

上述程式會生成一個不安全的查詢:

SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';

攻擊者可能輕鬆利用這個漏洞。

安全的方式:參數化查詢

使用參數化查詢,將資料與查詢分開處理,惡意輸入將不會被解釋為 SQL 指令。例如:

query = "SELECT * FROM users WHERE username = %s AND password = %s;"
cursor.execute(query, [username, password])

這裡的 %s 是一個佔位符(placeholder),psycopg 會將 usernamepassword 的值正確地插入查詢,確保它們只是普通的文字。

假設 username="admin"password="' OR '1'='1",最終執行的查詢是:

SELECT * FROM users WHERE username = 'admin' AND password = '\' OR \'1\'=\'1';
Django ORM 的自動防護

在 Django 的 ORM 中,參數化查詢是內建的功能,ORM 會自動幫你處理參數,預防 SQL Injection。

範例: 假設你要查詢特定使用者:

User.objects.filter(username="admin", password="' OR '1'='1'")

Django 會自動生成安全的 SQL 查詢,效果類似這樣:

SELECT * FROM users WHERE username = 'admin' AND password = '\' OR \'1\'=\'1';
圖解參數化查詢的作用

以下用圖解幫助你理解:

不安全的查詢:
User Input (惡意 SQL) --> 拼接成整條 SQL 查詢 --> 攻擊成功

參數化查詢:
User Input (惡意 SQL) --> 傳遞作為純資料 --> 無法改變查詢邏輯

延伸閱讀:SQL 注入攻擊全解析:從入門到防禦實戰指南

PostgreSQL 執行查詢

  • 當 SQL 語句到達 PostgreSQL 後,資料庫引擎負責執行該查詢,並根據請求返回結果。
  • 假如查詢是一個 SELECT 操作,PostgreSQL 會返回查詢結果(如資料表中的列和行);如果是更新或刪除操作,則返回影響的行數。

處理返回資料

  • psycopg 負責接收來自 PostgreSQL 的回應結果,並將其轉換為 Python 可處理的資料格式。
  • 舉例:
    • 如果 PostgreSQL 返回一個資料列,psycopg 會將其轉換為 Python 的 tupledict
    • 例如,從資料庫取出的值 [1, "Django"],可能會以 Python 的結構形式返回: (1, "Django")

Django 封裝資料

  • 接收到 psycopg 傳回的資料後,Django 會將其進一步處理,封裝為高層次的 Python 資料結構。
  • 如果查詢是基於 Django 模型(Model)的,返回的結果會是一組 ORM 物件: books = Book.objects.filter(title="Django") for book in books: print(book.title)
    • 這些 ORM 物件讓開發者可以使用熟悉的 Python 方法與資料互動,而不需要直接處理底層 SQL。

核心角色:

  • Django ORM:負責生成 SQL 語句,並將高階 Python 語法轉換為資料庫可執行的查詢。
  • psycopg:負責 Django 與 PostgreSQL 之間的溝通橋樑,執行 SQL 語句並處理資料庫協議。
  • PostgreSQL:資料實際存取的核心,執行查詢並返回結果。

這樣的分工讓開發者能專注於高階業務邏輯,而不需深究底層資料庫操作,進一步提高了開發效率與程式的可維護性。


psycopg3 的進階特性

psycopg3psycopg2 的升級版本,具備以下優勢:

  • 非同步操作:適合高併發應用。
  • 靈活配置:可根據需求進行擴展。
  • 與 psycopg2 相容:易於遷移現有專案。

如果您的應用需要高效能或非同步支援,可以考慮使用 psycopg3

pip install "psycopg[binary]"

總結

  • psycopg 是 Python 與 PostgreSQL 之間的橋樑,提供高效穩定的資料庫操作能力。
  • Django 利用 psycopg 作為驅動程式,讓開發者能通過 ORM 以簡單方式操作資料庫。
  • 使用步驟:
    1. 安裝 psycopg 驅動程式。
    2. 配置 settings.py 資料庫連接。
    3. 測試連接並開始操作資料庫。

如果您需要更高效的操作,可考慮使用 psycopg3

透過 psycopg,Python 與 PostgreSQL 的整合變得簡單高效,是開發現代應用程式的首選工具之一!

Similar Posts