Your own models
Ledger rows can’t change. So keep your own data, like the customer or the wallet type, in your own models, and point them at the ledger account.
pledge’s tables live in their own pledge schema and the app label is pledge, so nothing
clashes. Import with an alias if the names collide in your code:
from django_pledge.models import Account as LedgerAccount
Link with a OneToOneField #
from django.db import models
class Wallet(models.Model):
customer = models.OneToOneField(Customer, on_delete=models.PROTECT, related_name="wallet")
account = models.OneToOneField(
"pledge.Account", on_delete=models.PROTECT, db_constraint=False, related_name="wallet"
)
Now you can go both ways, and filter on ledger fields:
wallet.account.balance
account.wallet.customer
Wallet.objects.filter(account__currency="EUR", account__balance__gt=0)
The pledge models sit on database views, and a view can’t be the target of a foreign key constraint. Django still joins and filters as usual.
Use a ForeignKey instead when several of your rows share one account.
Create both in one transaction:
from django.db import transaction
with transaction.atomic():
customer = Customer.objects.create(name="Alice", email="alice@example.com")
account = Account.objects.create(
name=f"wallet:{customer.email}", currency="EUR", allow_negative_balance=False
)
Wallet.objects.create(customer=customer, account=account)
Add methods with a proxy model #
Want methods on the account itself? Use a proxy model:
from django_pledge.models import Account
class WalletAccount(Account):
class Meta:
proxy = True
def can_pay(self, amount):
return not self.is_closed and self.balance >= amount
WalletAccount.objects.get(pk=wallet.account_id).can_pay(Decimal("20"))
class CustomerAccount(Account) without proxy = True is refused with ImproperlyConfigured.
Use a OneToOneField for extra data, and a proxy for extra methods.
Store ids in your own tables #
These fields store pledge ids with the right column type:
| Field | Holds |
|---|---|
AccountIdField |
an account id (pla_…) |
TransferIdField |
a transfer id (plt_…), handy for safe retries |
EntryIdField |
an entry id (ple_…) |
NumericField |
an amount, as unbounded numeric like pledge’s |
from django_pledge import TransferIdField
Admin #
ReadOnlyAdmin shows ledger rows in the admin without add, change or delete:
from django.contrib import admin
from django_pledge.admin import ReadOnlyAdmin
from django_pledge.models import Account
@admin.register(Account)
class AccountAdmin(ReadOnlyAdmin, admin.ModelAdmin):
list_display = ["id", "name", "currency", "balance", "closed_at"]