Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

Django 信號處理:如何在保存前自動處理圖片

最後更新:2024年12月26日Python

本文為圖片轉 WebP 功能模組化系列文,第 1 篇:

  1. 如何設計 Django 的通用工具,並選擇適合的存放位置
  2. 從零開始:如何實現圖片轉 WebP 並上傳到 S3 的功能
  3. 使用基類模型(class model)優化代碼:從零到掌握 DRY 原則
  4. Django 抽象模型:理解 class Meta: abstract = True
  5. 為什麼要分離圖片處理邏輯?Django 最佳實踐指南
  6. Django 信號處理:如何在保存前自動處理圖片 👈 所在位置
  7. Django 信號處理的最佳實踐:如何選擇合適的位置
  8. 將圖片處理移至信號:模型設計的最佳實踐
  9. 理解 Python 的方法解析順序 (MRO):Django 多重繼承的最佳實踐

建議閱讀本文前,先閱讀完 圖片轉 WebP 系列文

在 Django 應用中,自動化圖片處理是一項常見需求。

通過信號處理,我們可以在模型的保存操作(save 方法)執行之前,自動執行圖片轉換和上傳等操作。

這篇文章將帶你了解如何實現這一功能,並詳解代碼中的核心邏輯,幫助新手掌握信號的運用。


信號代碼示例

以下是一段完整的信號處理邏輯代碼示例:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from users.models import Profile

@receiver(pre_save, sender=Profile)
def process_profile_image(sender, instance, **kwargs):
    if instance.photo and not getattr(instance, '_is_photo_processed', False):
        instance._is_photo_processed = True
        instance.process_and_upload_image(instance.photo, "profile_photos/")

信號邏輯的作用

信號邏輯的核心目的,是在模型保存前處理圖片並更新數據庫欄位,具體包括以下步驟:

檢查圖片字段是否存在

if instance.photo:

這一步確保只有當 photo 字段有值時,才執行圖片處理邏輯。

如果 photo 為空(None),信號邏輯會跳過,避免不必要的操作。


避免無限遞歸

為防止信號邏輯多次觸發導致的無限遞歸,代碼使用了以下邏輯:

if not getattr(instance, '_is_photo_processed', False):
    instance._is_photo_processed = True
  • getattr 函數:檢查 _is_photo_processed 屬性是否存在。如果該屬性不存在或為 False,表示圖片尚未處理,繼續執行邏輯。
  • 設置標誌位:在處理圖片後,設置 _is_photo_processed = True,避免重複處理圖片。

執行圖片處理

instance.process_and_upload_image(instance.photo, "profile_photos/")

這一步調用了自定義的圖片處理方法,負責以下操作:

  1. 將圖片轉換為 WebP 格式。
  2. 上傳處理後的圖片到 S3 存儲。
  3. 返回處理後的圖片路徑。

更新數據庫欄位

instance.photo = new_image_path

處理完成後,將 photo 字段更新為新的圖片路徑。

這樣,在數據保存到數據庫之前,圖片的欄位已經包含了處理後的正確鏈接。


信號邏輯的流程總結

整個信號邏輯可以用以下步驟總結:

  1. 收到保存信號 (pre_save)
    • 信號觸發後,檢查是否需要處理圖片。
  2. 檢查條件
    • 確保 photo 字段有值。
    • 確保 _is_photo_processed 為 False,避免重複處理。
  3. 處理圖片
    • 將圖片轉換為 WebP 格式並上傳到 S3。
    • 更新 photo 字段為新的圖片路徑。
  4. 保存數據
    • 信號完成後,模型繼續執行 save 方法,將處理後的數據保存到數據庫。

信號中的關鍵概念

getattr 函數的作用

getattr 是 Python 的內置函數,用於動態獲取對象屬性值。

其語法為:

getattr(object, name[, default])
  • object:要檢查的對象。
  • name:屬性名稱,作為字符串傳入。
  • default(可選):如果屬性不存在,則返回的默認值。

示例

class MyClass:
    def __init__(self):
        self.attribute = "Hello"

obj = MyClass()
print(getattr(obj, "attribute"))  # 輸出: Hello
print(getattr(obj, "non_existent", "Default Value"))  # 輸出: Default Value

在信號中的應用

not getattr(instance, '_is_photo_processed', False)
  • 確保屬性 _is_photo_processed 存在且為 False,避免重複處理。
  • 如果屬性不存在,返回默認值 False。

not 運算的作用

not 是邏輯運算符,用於對布爾值取反。

示例

條件結果
not TrueFalse
not FalseTrue
結果False
結果True

在信號邏輯中:

if not getattr(instance, '_is_photo_processed', False):
  • 如果 _is_photo_processed 為 True,條件不成立。
  • 如果 _is_photo_processed 為 False 或屬性不存在,條件成立。

處理結果

經過信號處理後,實現以下效果:

  1. 圖片轉換與上傳
    • 圖片被轉換為 WebP 格式,並上傳至 S3 存儲。
  2. 數據庫記錄更新
    • photo 字段更新為處理後圖片的路徑,例如: profile_photos/unique_image_id.webp
  3. 防止重複處理
    • _is_photo_processed 標誌確保信號只執行一次,避免無限遞歸。

總結

通過本文,你學習了如何使用 Django 信號處理模型的保存邏輯,自動執行圖片的轉換和上傳。

以下是重點總結:

  • 使用 pre_save 信號在保存數據前執行圖片處理。
  • 利用 getattr 和邏輯判斷避免重複處理。
  • 在保存到數據庫之前更新數據欄位,確保數據一致性。

這種設計不僅提高了代碼的自動化程度,還保證了圖片數據的完整性和正確性,是開發 Django 項目時的實用技巧! 🎯

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

Python

目錄

  • 信號代碼示例
  • 信號邏輯的作用
  • 檢查圖片字段是否存在
  • 避免無限遞歸
  • 執行圖片處理
  • 更新數據庫欄位
  • 信號邏輯的流程總結
  • 信號中的關鍵概念
  • getattr 函數的作用
  • not 運算的作用
  • 處理結果
  • 總結