-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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