Skip to content

Instantly share code, notes, and snippets.

@danny-ell77
Last active December 15, 2024 19:19
Show Gist options
  • Select an option

  • Save danny-ell77/825bf318c1cfa810e87c80e0f8e6cc51 to your computer and use it in GitHub Desktop.

Select an option

Save danny-ell77/825bf318c1cfa810e87c80e0f8e6cc51 to your computer and use it in GitHub Desktop.
Code demonstrating how to effectively use django's models.JSONField to achieve flexibility in modelling data
from typing import Optional
from django.core.exceptions import ValidationError
from django.db import models
from pydantic import BaseModel, EmailStr, PydanticValidationError
class CreditCardSchema(BaseModel):
number: str
expiry_month: int
expiry_year: int
cvv: str
class PayPalSchema(BaseModel):
email: EmailStr
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
class Currencies(models.TextChoices):
USD = "USD", "US Dollar"
EUR = "EUR", "Euro"
GBP = "GBP", "British Pound"
BTC = "BTC", "Bitcoin"
class TransactionStatuses(models.TextChoices):
PENDING = "PENDING", "Pending"
COMPLETED = "COMPLETED", "Completed"
FAILED = "FAILED", "Failed"
REFUNDED = "REFUNDED", "Refunded"
def payment_method_validator(value: Optional[dict]):
if value is None:
return
try:
PaymentMethodSchema(**value)
except PydanticValidationError as e:
raise ValidationError(e.errors())
class Transaction(models.Model):
processor_reference = models.CharField(max_length=96)
status = models.CharField(max_length=50, choices=TransactionStatuses.choices)
transaction_date = models.DateTimeField(auto_now_add=True)
amount = models.DecimalField(max_digits=8, decimal_places=2)
currency = models.CharField(
max_length=10,
choices=Currencies.choices,
null=True,
)
payment_method = models.JSONField(
validators=[payment_method_validator], null=True, blank=True
)
def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment