18.8.2008

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)  

← Back to blog