在本文中,我將簡要介紹一些最佳實踐,這些最佳實踐在使用 Alembic 和 SQLAlchemy 時幫助保持專案有序、簡化資料庫維護並防止常見陷阱。這些技巧不只一次讓我擺脫了麻煩。以下是我們將要介紹的內容:
- 命名約定
- 依日期對遷移進行排序
- 表格、欄位與遷移註解
- 無模型遷移中的資料處理
- 遷移測驗(樓梯測驗)
- 運行遷移的服務
- 模型使用 Mixins
1. 命名約定
SQLAlchemy 允許您設定命名約定,在產生遷移時自動套用至所有資料表和約束。這使您無需手動命名索引、外鍵和其他約束,從而使資料庫結構可預測且一致。
要在新專案中進行設置,請在基底類別中新增約定,以便 Alembic 將自動使用所需的命名格式。以下是大多數情況下都有效的約定範例:
from sqlalchemy import MetaData from sqlalchemy.orm import DeclarativeBase convention = { 'all_column_names': lambda constraint, table: '_'.join( [column.name for column in constraint.columns.values()] ), 'ix': 'ix__%(table_name)s__%(all_column_names)s', 'uq': 'uq__%(table_name)s__%(all_column_names)s', 'ck': 'ck__%(table_name)s__%(constraint_name)s', 'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s', 'pk': 'pk__%(table_name)s', } class BaseModel(DeclarativeBase): metadata = MetaData(naming_convention=convention)
2. 依日期對遷移進行排序
Alembic 遷移檔案名稱通常以修訂標籤開頭,這可以使目錄中的遷移順序顯得隨機。有時按時間順序排列它們很有用。
Alembic 允許使用 file_template 設定在 alembic.ini 檔案中自訂移轉檔案名稱範本。以下是兩種方便的命名格式,可讓遷移保持井井有條:
- 基於日期:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
- 基於 Unix 時間戳記:
file_template = %%(epoch)d_%%(rev)s_%%(slug)s
在檔案名稱中使用日期或 Unix 時間戳可以讓遷移保持井井有條,使導航更容易。我更喜歡使用 Unix 時間戳,下一節將提供一個範例。
3. 表和遷移的註釋
對於在團隊中工作的人來說,註釋屬性是一個很好的做法。對於 SQLAlchemy 模型,請考慮直接向列和表添加註釋,而不是依賴文件字串。這樣,註釋在程式碼和資料庫中都可用,使 DBA 或分析師更容易理解表格和欄位的用途。
class Event(BaseModel): __table_args__ = {'comment': 'System (service) event'} id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, comment='Event ID - PK', ) service_id: Mapped[int] = mapped_column( sa.Integer, sa.ForeignKey( f'{IntegrationServiceModel.__tablename__}.id', ondelete='CASCADE', ), nullable=False, comment='FK to integration service that owns the event', ) name: Mapped[str] = mapped_column( sa.String(256), nullable=False, comment='Event name' )
為遷移添加註解也很有幫助,以便更容易在檔案系統中找到它們。可以使用 -m
from sqlalchemy import MetaData from sqlalchemy.orm import DeclarativeBase convention = { 'all_column_names': lambda constraint, table: '_'.join( [column.name for column in constraint.columns.values()] ), 'ix': 'ix__%(table_name)s__%(all_column_names)s', 'uq': 'uq__%(table_name)s__%(all_column_names)s', 'ck': 'ck__%(table_name)s__%(constraint_name)s', 'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s', 'pk': 'pk__%(table_name)s', } class BaseModel(DeclarativeBase): metadata = MetaData(naming_convention=convention)
4. 避免在遷移中使用模型
模型通常用於資料操作,例如將資料從一個表傳輸到另一個表或修改列值。但是,如果模型在建立遷移後發生更改,則在遷移中使用 ORM 模型可能會導致問題。在這種情況下,基於舊模型的遷移在執行時將會中斷,因為資料庫架構可能不再與目前模型相符。
遷移應該是靜態的並且獨立於模型的當前狀態,以確保無論程式碼如何更改都能正確執行。以下是避免使用模型進行資料操作的兩種方法。
- 使用原始 SQL 進行資料運算:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
- 直接在遷移定義表: 如果想使用SQLAlchemy進行資料操作,可以直接在遷移中手動定義表。這確保了遷移執行時的靜態模式,並且不會依賴模型中的變更。
file_template = %%(epoch)d_%%(rev)s_%%(slug)s
5. 遷移測試的階梯測試
階梯測試涉及逐步測試升級/降級遷移,以確保整個遷移鏈正常運作。這確保每次遷移都可以成功地從頭開始建立新資料庫並降級而不會出現問題。將此測試添加到 CI 對於團隊來說非常寶貴,可以節省時間並減少挫折感。
將測試整合到您的專案中可以輕鬆快速地完成。您可以在此存儲庫中找到程式碼範例。它還包括其他可能有幫助的有價值的遷移測試。
6. 遷移服務
用於執行遷移的單獨服務。這只是執行遷移的一種方法。當在本地或類似開發的環境中開發時,這種方法非常適合。我想提醒您有關條件 dependent_on 功能,該功能與此處相關。我們使用 Alembic 獲取應用程式映像並在單獨的容器中運行它。我們新增對資料庫的依賴關係,條件是僅當資料庫準備好處理請求(service_healthy)時才開始遷移。此外,可以為應用程式新增條件依賴項(service_completed_successively),確保它僅在遷移成功完成後啟動。
class Event(BaseModel): __table_args__ = {'comment': 'System (service) event'} id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, comment='Event ID - PK', ) service_id: Mapped[int] = mapped_column( sa.Integer, sa.ForeignKey( f'{IntegrationServiceModel.__tablename__}.id', ondelete='CASCADE', ), nullable=False, comment='FK to integration service that owns the event', ) name: Mapped[str] = mapped_column( sa.String(256), nullable=False, comment='Event name' )
depends_on 條件確保遷移僅在資料庫完全準備好後運行,並且應用程式在遷移完成後啟動。
7. 模型的 Mixins
雖然這可能是顯而易見的一點,但重要的是不要忽視它。使用 mixins 是避免程式碼重複的便捷方法。 Mixin 是包含常用欄位和方法的類,可以將其整合到需要的任何模型中。例如,我們經常需要created_at和updated_at欄位來追蹤記錄的建立和更新時間。使用基於 UUID 的 id 來標準化主鍵也很有用。所有這些都可以封裝在 mixin 中。
from sqlalchemy import MetaData from sqlalchemy.orm import DeclarativeBase convention = { 'all_column_names': lambda constraint, table: '_'.join( [column.name for column in constraint.columns.values()] ), 'ix': 'ix__%(table_name)s__%(all_column_names)s', 'uq': 'uq__%(table_name)s__%(all_column_names)s', 'ck': 'ck__%(table_name)s__%(constraint_name)s', 'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s', 'pk': 'pk__%(table_name)s', } class BaseModel(DeclarativeBase): metadata = MetaData(naming_convention=convention)
透過新增這些 mixins,我們可以在需要的任何模型中包含 UUID id 和時間戳記:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
結論
處理遷移可能具有挑戰性,但遵循這些簡單的做法有助於保持專案井然有序且易於管理。命名約定、日期排序、註釋和測試使我免於混亂並有助於防止錯誤。我希望這篇文章對您有所幫助——請隨時在評論中分享您自己的遷移技巧!
以上是Alembic 和 SQLAlchemy 的最佳實踐的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和C 各有優勢,選擇應基於項目需求。 1)Python適合快速開發和數據處理,因其簡潔語法和動態類型。 2)C 適用於高性能和系統編程,因其靜態類型和手動內存管理。

選擇Python還是C 取決於項目需求:1)如果需要快速開發、數據處理和原型設計,選擇Python;2)如果需要高性能、低延遲和接近硬件的控制,選擇C 。

通過每天投入2小時的Python學習,可以有效提升編程技能。 1.學習新知識:閱讀文檔或觀看教程。 2.實踐:編寫代碼和完成練習。 3.複習:鞏固所學內容。 4.項目實踐:應用所學於實際項目中。這樣的結構化學習計劃能幫助你係統掌握Python並實現職業目標。

在兩小時內高效學習Python的方法包括:1.回顧基礎知識,確保熟悉Python的安裝和基本語法;2.理解Python的核心概念,如變量、列表、函數等;3.通過使用示例掌握基本和高級用法;4.學習常見錯誤與調試技巧;5.應用性能優化與最佳實踐,如使用列表推導式和遵循PEP8風格指南。

Python適合初學者和數據科學,C 適用於系統編程和遊戲開發。 1.Python簡潔易用,適用於數據科學和Web開發。 2.C 提供高性能和控制力,適用於遊戲開發和系統編程。選擇應基於項目需求和個人興趣。

Python更適合數據科學和快速開發,C 更適合高性能和系統編程。 1.Python語法簡潔,易於學習,適用於數據處理和科學計算。 2.C 語法複雜,但性能優越,常用於遊戲開發和系統編程。

每天投入兩小時學習Python是可行的。 1.學習新知識:用一小時學習新概念,如列表和字典。 2.實踐和練習:用一小時進行編程練習,如編寫小程序。通過合理規劃和堅持不懈,你可以在短時間內掌握Python的核心概念。

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

Atom編輯器mac版下載
最受歡迎的的開源編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!