Django 1.0 custom admin two fields shown as one
I needed a way to have two model fields to be shown/edited on one form field. And I came up with the following.
(CurrencyField (expense) shows and edits fields value and currency in the actual model)
from django.contrib import admin
from budget.models import Expense
from django import forms
from django.forms.util import ValidationError
class CurrencyField(forms.CharField):
def clean(self, value):
amount = 0
currency = ''
try:
amount = float(value.split(" ")[0].strip())
except (ValueError, TypeError), te:
raise ValidationError('Amount is incorrect!')
try:
currency = value.split(" ")[1].strip().upper()
if len(currency) != 3:
raise TypeError('cur')
except (ValueError, TypeError), te:
raise ValidationError('Currency is incorrect! Should be three letter universal sign (e.g. EUR)')
return (amount, currency)
class ExpenseForm(forms.ModelForm):
expense = CurrencyField()
def __init__(self, *args, **kwargs):
super(ExpenseForm, self).__init__(*args, **kwargs)
self.initial['expense'] = "%s %s" % (self.instance.value or '',
self.instance.currency or '')
def save(self, commit=True):
self.instance.value, self.instance.currency = self.cleaned_data['expense']
return super(ExpenseForm, self).save(commit)
class Meta:
model = Expense
# Note added:
# Expense is like this:
# class Expense(models.Model):
# ...
# value = models.FloatField(...) # This contains the amount of currency, like 120.32
# currency = models.CharField(...) # Currency is e.g. 'USD', 'EUR' identifier of currency
# ...
class ExpenseAdmin(admin.ModelAdmin):
list_display = ('date', 'time', 'local_currency', 'in_euro', 'description', 'tags')
ordering = ('date','time')
form = ExpenseForm
fields = ('expense', 'date', 'time', 'description', 'tags')
admin.site.register(Expense, ExpenseAdmin)