Skip to Content
FeaturesModulesCurrencyAdmin Integration

Admin Integration

Django-CFG provides seamless admin integration for MoneyField with automatic widget detection and a dedicated display field.

Overview

No extra mixins needed! PydanticAdmin automatically includes MoneyFieldAdminMixin. Just inherit from PydanticAdmin and the currency features work out of the box.

ComponentPurpose
PydanticAdminBase admin class (includes MoneyFieldAdminMixin)
MoneyFieldDisplayDisplay field for admin lists
MoneyFieldWidgetForm widget for editing (auto-applied)

MoneyFieldDisplay

Compact display field for admin lists. Auto-detects related fields from the base name.

Import

from django_cfg.modules.django_admin import MoneyFieldDisplay

Basic Usage

from django_cfg.modules.django_admin import AdminConfig, MoneyFieldDisplay config = AdminConfig( model=Vehicle, list_display=["id", "name", "price"], display_fields=[ # Auto-detects: price_currency, price_target, price_rate, price_rate_at MoneyFieldDisplay( name="price", title="Price", ), ], )

What it displays:

₩15,700,000 → $10,645.05 Rate: 0.000678 • 2h ago

Parameters

ParameterTypeDefaultDescription
namestrRequiredBase field name (e.g., “price”)
titlestrNoneColumn header title
currency_fieldstr{name}_currencyField with currency code
target_fieldstr{name}_targetField with converted amount
target_currencystr"USD"Target currency code
rate_fieldstr{name}_rateField with exchange rate
rate_at_fieldstr{name}_rate_atField with rate timestamp
show_rateboolTrueShow rate info line
precisionint2Decimal places
compactboolTrueSingle-line display

Explicit Field Names

Override auto-detected field names if needed:

MoneyFieldDisplay( name="price", title="Price", currency_field="price_currency", target_field="price_target", target_currency="USD", rate_field="price_rate", rate_at_field="price_rate_at", )

Display Options

MoneyFieldDisplay( name="price", title="Price", show_rate=False, # Hide rate info line precision=0, # No decimals compact=False, # Multi-line display )

MoneyFieldWidget

Auto-applied to MoneyField in admin forms. No configuration needed.

Visual Layout

┌─────────────────────────────────────────────────────────────┐ │ Amount │ Currency │ │ ┌──────────────────────┐ │ ┌──────────────────────────┐ │ │ │ 50,000,000 │ │ │ KRW ▼ │ │ │ └──────────────────────┘ │ └──────────────────────────┘ │ │ → $33,900 | 1 KRW = 0.000678 USD • 2h ago [rates ↗] │ └─────────────────────────────────────────────────────────────┘

Features

  • Amount input (2/3 width) + Currency dropdown (1/3 width)
  • Live conversion updates as you type (Alpine.js)
  • Rate info with timestamp (“2h ago”)
  • Link to CurrencyRate admin for rate management
  • Dark mode support

Live Recalculation

When you change currency or amount:

  1. Widget reads rates from embedded JSON (passed at render)
  2. Alpine.js recalculates conversion
  3. Display updates instantly (no server roundtrip)

Complete Example

from django.contrib import admin from django_cfg.modules.django_admin import ( AdminConfig, MoneyFieldDisplay, FieldsetConfig, ShortUUIDField, BadgeField, ) from django_cfg.modules.django_admin.base import PydanticAdmin from .models import Vehicle config = AdminConfig( model=Vehicle, # Performance select_related=["source", "brand"], # List view columns list_display=["id", "name", "price", "status"], # Display field configurations display_fields=[ ShortUUIDField(name="id", title="ID"), # MoneyFieldDisplay - auto-detects all price-related fields MoneyFieldDisplay( name="price", title="Price", ), BadgeField( name="status", title="Status", label_map={ "active": "success", "sold": "danger", }, ), ], # Form fieldsets fieldsets=[ FieldsetConfig( title="Basic Info", fields=["name", "status"], ), FieldsetConfig( title="Pricing", fields=["price"], # MoneyFieldWidget auto-applied ), ], ) @admin.register(Vehicle) class VehicleAdmin(PydanticAdmin): """PydanticAdmin includes MoneyFieldAdminMixin automatically.""" config = config

How MoneyFieldAdminMixin Works

MoneyFieldAdminMixin is automatically included in PydanticAdmin. Here’s what it provides:

1. Auto-Detection of MoneyField

On admin init, it scans the model for MoneyField instances and registers related fields.

2. Readonly Fields

Automatically adds _target, _rate, _rate_at as readonly fields:

def get_readonly_fields(self, request, obj=None): readonly = list(super().get_readonly_fields(request, obj)) for field_name in self._get_money_field_names(): for suffix in ["_target", "_rate", "_rate_at"]: aux_field = f"{field_name}{suffix}" if self._field_exists(aux_field): readonly.append(aux_field) return readonly

3. Widget Assignment

Replaces default widget with MoneyFieldWidget:

def formfield_for_dbfield(self, db_field, request, **kwargs): if db_field.__class__.__name__ == "MoneyField": kwargs["widget"] = MoneyFieldWidget( default_currency=current_currency, target_currency=target_currency, ) return super().formfield_for_dbfield(db_field, request, **kwargs)

4. Currency Saving

Handles currency field saving from POST data:

def save_model(self, request, obj, form, change): for field_name in self._get_money_field_names(): currency_key = f"{field_name}_currency" if currency_key in request.POST: setattr(obj, currency_key, request.POST[currency_key]) super().save_model(request, obj, form, change)

Currency Symbols

MoneyFieldDisplay includes built-in currency symbols:

CodeSymbol
USD$
EUR
GBP£
JPY¥
KRW
CNY¥
RUB
BTC
ETHΞ

Unknown currencies display as "CODE " (code + space).


Troubleshooting

Widget Not Appearing

Make sure you’re using PydanticAdmin:

from django_cfg.modules.django_admin.base import PydanticAdmin @admin.register(Vehicle) class VehicleAdmin(PydanticAdmin): # ✅ Correct config = config

Currency Not Saving

Check that the form includes the currency field in POST data. The widget automatically handles this.

Conversion Shows “N/A”

  1. Check that rates exist in CurrencyRate table
  2. Click “Update All Rates” in CurrencyRate admin
  3. Verify price_currency has a value

See Also

Last updated on