在本文中,我將引導您了解如何使用Django 的JSONField(JSON 和JSONB 包裝器)對半結構化資料進行建模,以及如何對其強制實施架構使用Pydantic 取得資料-對於Python Web 開發人員來說,這種方法應該很自然。
靈活的類型定義
讓我們考慮一個處理付款的系統,例如交易表。它看起來像這樣:
from django.db import models class Transaction(models.Model): # Other relevant fields... payment_method = models.JSONField(default=dict, null=True, blank=True)
我們的重點是 payment_method 欄位。在現實世界中,我們將擁有處理付款的現有方法:
信用卡
PayPal
現在購買,稍後付款
加密貨幣
我們的系統必須能夠適應儲存每種付款方式所需的特定數據,同時保持一致且可驗證的結構。
我們將使用 Pydantic 為不同的付款方式定義精確的模式:
from typing import Optional from pydantic import BaseModel class CreditCardSchema(BaseModel): last_four: str expiry_month: int expiry_year: int cvv: str class PayPalSchema(BaseModel): email: EmailStr account_id: str class CryptoSchema(BaseModel): wallet_address: str network: Optional[str] = None class BillingAddressSchema(BaseModel): street: str city: str country: str postal_code: str state: Optional[str] = None class PaymentMethodSchema(BaseModel): credit_card: Optional[CreditCardSchema] = None paypal: Optional[PayPalSchema] = None crypto: Optional[CryptoSchema] = None billing_address: Optional[BillingAddressSchema] = None
這個方法有幾個顯著的好處:
一次只能有一種付款方式具有非空值。
無需複雜的資料庫遷移即可輕鬆擴展或修改。
確保模型層級的資料完整性。
為了在 payment_method 欄位上強制執行架構,我們利用 Pydantic 模型來確保傳遞到該欄位的任何資料都與我們定義的架構一致。
from typing import Optional, Mapping, Type, NoReturn from pydantic import ValidationError as PydanticValidationError from django.core.exceptions import ValidationError def payment_method_validator(value: Optional[dict]) -> Optional[Type[BaseModel] | NoReturn]: if value is None: return if not isinstance(value, Mapping): raise TypeError("Payment method must be a dictionary") try: PaymentMethodSchema(**value) except (TypeError, PydanticValidationError) as e: raise ValidationError(f"Invalid payment method: {str(e)}")
在這裡,我們執行一些檢查,以確保輸入驗證器的資料類型正確,以便 Pydantic 可以驗證它。我們對可為 null 的值不執行任何操作,如果傳入的值不是 Mapping 類型的子類別(例如 Dict 或 OrderedDict),則會引發類型錯誤。
當我們使用傳遞給建構函數的值來建立 Pydantic 模型的實例時。如果值的結構不符合 PaymentMethodSchema 定義的架構,Pydantic 將引發驗證錯誤。例如,如果我們在 PayPalSchema 中為電子郵件欄位傳遞無效的電子郵件值,Pydantic 將引發如下驗證錯誤:
ValidationError: 1 validation error for PaymentMethodSchema paypal.email value is not a valid email address: An email address must have an @-sign. [type=value_error, input_value='Check me out on LinkedIn: https://linkedin.com/in/daniel-c-olah', input_type=str]
我們可以透過兩種方式強制執行此驗證:
-
自訂驗證方法
在儲存過程中,我們呼叫驗證函數以確保付款方式與預期模式相符。
from django.db import models class Transaction(models.Model): # ... other fields ... payment_method = models.JSONField(null=True, blank=True) def save(self, *args, **kwargs): # Override save method to include custom validation payment_method_validator(self.payment_method) super().save(*args, **kwargs)
雖然有效,但這種方法在 Django 中可能會變得麻煩且不太慣用。我們甚至可以用具有相同功能的類別方法來替換該函數,以使程式碼更簡潔。
-
使用欄位驗證器
此方法利用了 Django 內建的欄位驗證機制:
from django.db import models class Transaction(models.Model): # Other relevant fields... payment_method = models.JSONField(default=dict, null=True, blank=True)
這種方法平衡了靈活性和對 payment_method 欄位中儲存的值的控制。它使我們能夠適應未來需求的變化,而不會損害該領域現有資料的完整性。例如,我們可以在 Paystack 架構中包含 Paystack ID 欄位。此更改將是無縫的,因為我們不必處理複雜的資料庫遷移。
我們甚至可以在未來添加 pay_later 方法,沒有任何麻煩。欄位的類型也可能會發生變化,我們不會面臨資料庫欄位遷移限制,就像從整數主鍵遷移到 UUID 主鍵時遇到的限制一樣。您可以在此處查看完整的程式碼以完全理解這個概念。
非規範化
反規範化涉及跨多個文件或集合故意複製數據,以優化效能和可擴展性。這種方法與傳統關聯式資料庫中使用的嚴格規範化形成鮮明對比,NoSQL 資料庫透過引入靈活的、以文件為導向的儲存範例,在普及非規範化方面發揮了重要作用。
考慮一個電子商務場景,其中產品和訂單有單獨的表。當客戶下訂單時,必須捕獲購物車中產品詳細資訊的快照。我們不會引用目前的產品記錄(該記錄可能會隨著時間的推移因更新或刪除而發生變化),而是直接將產品資訊儲存在訂單中。這可確保訂單保留其原始上下文和完整性,反映購買時產品的確切狀態。非規範化在實現這種一致性方面發揮著至關重要的作用。
一種可能的方法可能涉及複製訂單表中的某些產品欄位。然而,這種方法可能會帶來可擴展性挑戰並損害訂單模式的內聚性。更有效的解決方案是將相關產品欄位序列化為 JSON 結構,讓訂單能夠維護產品的獨立記錄,而不需要依賴外部查詢。下面的程式碼說明了這個技巧:
from typing import Optional from pydantic import BaseModel class CreditCardSchema(BaseModel): last_four: str expiry_month: int expiry_year: int cvv: str class PayPalSchema(BaseModel): email: EmailStr account_id: str class CryptoSchema(BaseModel): wallet_address: str network: Optional[str] = None class BillingAddressSchema(BaseModel): street: str city: str country: str postal_code: str state: Optional[str] = None class PaymentMethodSchema(BaseModel): credit_card: Optional[CreditCardSchema] = None paypal: Optional[PayPalSchema] = None crypto: Optional[CryptoSchema] = None billing_address: Optional[BillingAddressSchema] = None
由於我們已經介紹了上一節中的大部分概念,您應該開始欣賞 Pydantic 在這一切中的作用。在上面的範例中,我們使用 Pydantic 來驗證連結到訂單的產品清單。透過定義產品結構的模式,Pydantic 確保添加到訂單中的每個產品都符合預期要求。如果提供的資料不符合架構,Pydantic 會引發驗證錯誤。
在 Django 查詢 JSONField
我們可以像在 Django 欄位中執行查找一樣查詢 JSONField 鍵。以下是基於我們的用例的一些範例。
from typing import Optional, Mapping, Type, NoReturn from pydantic import ValidationError as PydanticValidationError from django.core.exceptions import ValidationError def payment_method_validator(value: Optional[dict]) -> Optional[Type[BaseModel] | NoReturn]: if value is None: return if not isinstance(value, Mapping): raise TypeError("Payment method must be a dictionary") try: PaymentMethodSchema(**value) except (TypeError, PydanticValidationError) as e: raise ValidationError(f"Invalid payment method: {str(e)}")
您可以查看文件以了解有關過濾 JSON 欄位的更多資訊。
結論
在 PostgreSQL 中使用 JSON 和 JSONB 為處理關聯式資料庫中的半結構化資料提供了極大的靈活性。 Pydantic 和 Django 的 JSONField 等工具有助於強制執行資料結構規則,從而更容易保持準確性並適應變化。然而,這種靈活性需要謹慎使用。如果沒有適當的規劃,隨著數據隨著時間的推移而變化,可能會導致效能下降或不必要的複雜性。
在 Django 中,只有在明確呼叫 full_clean() 時才會觸發欄位驗證器 - 這通常發生在使用 Django Forms 或在 DRF 序列化器上呼叫 is_valid() 時。更多詳細信息,您可以參考 Django 驗證器文件。
解決此問題的更高級方法是實作一個自訂 Django 字段,該字段整合 Pydantic 以在內部處理 JSON 資料的序列化和驗證。雖然這需要一篇專門的文章,但目前,您可以探索為該問題提供現成解決方案的庫,例如:django-pydantic-jsonfield
以上是如何使用 JSONField 和 Pydantic 在 Django 中建立靈活的資料模型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

ForhandlinglargedatasetsinPython,useNumPyarraysforbetterperformance.1)NumPyarraysarememory-efficientandfasterfornumericaloperations.2)Avoidunnecessarytypeconversions.3)Leveragevectorizationforreducedtimecomplexity.4)Managememoryusagewithefficientdata

Inpython,ListSusedynamicMemoryAllocationWithOver-Asalose,而alenumpyArraySallaySallocateFixedMemory.1)listssallocatemoremoremoremorythanneededinentientary上,respizeTized.2)numpyarsallaysallaysallocateAllocateAllocateAlcocateExactMemoryForements,OfferingPrediCtableSageButlessemageButlesseflextlessibility。

Inpython,YouCansspecthedatatAtatatPeyFelemereModeRernSpant.1)Usenpynernrump.1)Usenpynyp.dloatp.dloatp.ploatm64,formor professisconsiscontrolatatypes。

NumPyisessentialfornumericalcomputinginPythonduetoitsspeed,memoryefficiency,andcomprehensivemathematicalfunctions.1)It'sfastbecauseitperformsoperationsinC.2)NumPyarraysaremorememory-efficientthanPythonlists.3)Itoffersawiderangeofmathematicaloperation

Contiguousmemoryallocationiscrucialforarraysbecauseitallowsforefficientandfastelementaccess.1)Itenablesconstanttimeaccess,O(1),duetodirectaddresscalculation.2)Itimprovescacheefficiencybyallowingmultipleelementfetchespercacheline.3)Itsimplifiesmemorym

SlicingaPythonlistisdoneusingthesyntaxlist[start:stop:step].Here'showitworks:1)Startistheindexofthefirstelementtoinclude.2)Stopistheindexofthefirstelementtoexclude.3)Stepistheincrementbetweenelements.It'susefulforextractingportionsoflistsandcanuseneg

numpyallowsforvariousoperationsonArrays:1)basicarithmeticlikeaddition,減法,乘法和division; 2)evationAperationssuchasmatrixmultiplication; 3)element-wiseOperations wiseOperationswithOutexpliitloops; 4)

Arresinpython,尤其是Throughnumpyandpandas,weessentialFordataAnalysis,offeringSpeedAndeffied.1)NumpyArseNable efflaysenable efficefliceHandlingAtaSetSetSetSetSetSetSetSetSetSetSetsetSetSetSetSetsopplexoperationslikemovingaverages.2)


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

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

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。