Monday, August 18, 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)

Tuesday, August 12, 2008

Django 1.0 admin custom inlines


...

class ChangeSetForm(forms.ModelForm):
dosomething = forms.BooleanField(label="Do something")
class Meta:
model = ChangeSet
exclude = ('modified',) # Note: This doesn't work!
fields = ('old_title',) # Note: This doesn't work!

ChangeSetInlineFormSet = inlineformset_factory(
Article, ChangeSet,
form = ChangeSetForm
)

class InlineChangeSet(admin.TabularInline):
model = ChangeSet
form = ChangeSetForm
extra = 0
raw_id_fields = ('editor',)
fields = ('old_title', ) # This works.

...

Completely custom inline (without delete checkbox etc)


coming...

Wednesday, July 16, 2008

Lighttpd 1.4.19 compiling (Debian etch)

Following explains briefly how I managed to compile and run Lighttpd.

Remember that this doesn't include init.d scripts and such, and is not great idea for production servers.

Using Debian repository installation of Lighttpd is advised, seek the older article of installing Django, I have exaplained it there.

# Dependencies:
sudo apt-get install libpcre3
sudo apt-get install libpcre3-dev
sudo apt-get install zlib1g
sudo apt-get install zlib1g-dev

# Compilation:
cd /usr/src/
sudo wget http://www.lighttpd.net/download/lighttpd-1.4.19.tar.gz
sudo tar -xvzf lighttpd-1.4.19.tar.gz
cd lighttpd-1.4.19
sudo ./configure
sudo make
sudo make install

ls -la /usr/local/sbin/ # should contain lighttpd (and lighttpd-angel)
ls -la /usr/local/lib/ # should contain whole bunch of mod_... files

# now since this is bare ass installation,
# we need to make init scripts and such ourselves
sudo adduser lighttpd

sudo apt-get install authbind
cd /etc/authbind/byport/
sudo touch 80
sudo chown lighttpd:lighttpd 80
sudo chmod 775 80

sudo mkdir /etc/lighttpd
sudo chown lighttpd:lighttpd /etc/lighttpd/
sudo su lighttpd

mkdir /home/lighttpd/public_html
pico /home/lighttpd/public_html/index.html
<html><body>Congrats I'm running!</body><html>
# Exit the pico

pico /etc/lighttpd/lighttpd.conf
server.document-root = "/home/lighttpd/public_html"
server.port = 80
index-file.names = ( "index.html", "index.htm" )
include_shell "/etc/lighttpd/create-mime.assign.pl"
# Exit the pico

pico /etc/lighttpd/create-mime.assign.pl
#!/usr/bin/perl -w
use strict;
open MIMETYPES, "/etc/mime.types" or exit;
print "mimetype.assign = (\n";
my %extensions;
while() {
chomp;
s/\#.*//;
next if /^\w*$/;
if(/^([a-z0-9\/+-.]+)\s+((?:[a-z0-9.+-]+[ ]?)+)$/) {
foreach(split / /, $2) {
# mime.types can have same extension for different
# mime types
next if $extensions{$_};
$extensions{$_} = 1;
print "\".$_\" => \"$1\",\n";
}
}
}
print ")\n";
# Exit the pico

/etc/lighttpd/create-mime.assign.pl

# Runs the lighttpd for test ^C to exit
authbind /usr/local/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf -D

exit # exits the "sudo su lighttpd"

Tuesday, July 15, 2008

Installation of MySQL server, MySQLdb, Flup, Lighttpd and Django (Debian etch)

Note: I have not tested it as is, I was writing this afterwards from memory, so beware of the errors.

Setting up debian


# logged in as root:
apt-get install sudo
adduser joe
sudoedit /etc/sudoers
joe ALL=(ALL) ALL # added this line

# Following is done in my own user (joe):
sudo apt-get upgrade
sudo dpkg-reconfigure locales
sudo tzselect
sudo apt-get install build-essential


Now to the installing Django and others...


# Python 2.5
sudo apt-get install python2.5
sudo rm /usr/bin/python
sudo ln -s /usr/bin/python /usr/bin/python2.5

python
Python 2.5 (release25-maint, Dec 9 2006, 14:35:53)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-20)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

# Storing downloaded/compiled python-modules:
sudo mkdir /usr/src/python-modules


# MySQL server:
sudo apt-get install mysql-server

# MySQLdb:
# Dependencies:
sudo apt-get install libmysqlclient15-dev
sudo apt-get install python2.5-dev

cd /usr/src/python-modules/
sudo wget http://mesh.dl.sourceforge.net/sourceforge/mysql-python/MySQL-python-1.2.2.tar.gz
sudo tar -xvzf MySQL-python-1.2.2.tar.gz
cd MySQL-python-1.2.2
python setup.py build
sudo python setup.py install
cd /usr/src/python-modules/

python
>>> import MySQLdb
>>>


# Flup (for the fastcgi):
cd /usr/src/python-modules/
svn co http://svn.saddi.com/flup/trunk/ flup-svn
cd flup-svn
sudo python setup.py install
cd /usr/src/python-modules/

python
>>> import flup
>>>


# Lighttpd (1.4.19) installation using Debian unstable repository:
# TODO: Coming...

# NOTE: My installation method of Django allows to use both, svn and release
# Django as far as you always run the wanted django using env PYTHONPATH...
# Django release installation:
cd /usr/src/python-modules/
sudo wget http://www.djangoproject.com/download/0.96.2/tarball/ # this one downloads Django-0.96.2.tar.gz
sudo tar -xvzf Django-0.96.2.tar.gz

env PYTHONPATH=$PYTHONPATH:/usr/src/python-modules/Django-0.96.2 python
>>> import django
>>>

# Django svn installation:
cd /usr/src/python-modules/
sudo svn co http://code.djangoproject.com/svn/django/trunk/ Django-svn

env PYTHONPATH=$PYTHONPATH:/usr/src/python-modules/Django-svn python
>>> import django
>>>

# Django new project and fastcgi server:
sudo mkdir /var/www-domains/

sudo adduser examplecom
sudo mkdir /var/www-domains/example.com/
sudo chown examplecom:examplecom /var/www/example.com
sudo chmod +s /var/www/example.com

sudo su examplecom
cd /var/www/example.com/
mkdir public
mkdir public_media
mkdir fastcgi-servers
mkdir django-projects

# TODO: More to come...