I got a little frustrated trying to find the ‘simple’ answer to change the html which is generated by the various form field widgets.
In this case the RadioSelect field generates radio buttons wrapped in an unordered list. It was annoying, and whilst I could resort to writing the html directly in the html; that’s not ideal.
The solution is not hard, just not well documented.
We need only write a “render” routine to return the string we want. Then override the default widget with our renderer, and finally specify all that in the form field definition:
from django import forms
from django.forms import ModelForm
from django.utils.safestring import mark_safe
from django.utils.encoding import force_unicode
FULFILMENT_CHOICES = (
('Post','Post'),
('Pickup','Pickup')
)
class MyRadioRenderer(forms.widgets.RadioFieldRenderer): """Render radio buttons without the <li>"""
def render(self):
return mark_safe(u'\n%s\n' % u'\n'.join([u'%s'
% force_unicode(w) for w in self]))
class OrderForm(ModelForm):
fulfilment = forms.ChoiceField(
widget=forms.RadioSelect(renderer=MyRadioRenderer),
choices=FULFILMENT_CHOICES)
Produces:
<div class="orderValue">
<label for="id_fulfilment_0"><input type="radio" id="id_fulfilment_0" value="Post" name="fulfilment"/> Post</label>
<label for="id_fulfilment_1"><input type="radio" id="id_fulfilment_1" value="Pickup" name="fulfilment"/> Pickup</label>
</div>
I have a user profile model which holds their ‘mugshot’ image. I’m using modelForm to to present a profile update form. It was easy to build a working form, but now I need a couple of tweaks to the image:
1) it saves with the filename that the user provides; I rather dictate the filename to use. I thought I’d just use the PK of the model, and the same file extension eg: “443.jpg”
2) it should replace the existing image, not append an underscore like “443___.jpg”.
Here’s my model and form:
class Member(models.Model):
home_phone = models.CharField(max_length=10, blank=True)
image = models.ImageField(upload_to='members', default="default.png")
...
class MemberProfileForm(forms.ModelForm):
home_phone = AUPhoneNumberField(required=False)
class Meta:
model = Member
exclude = ('email','password','create_date','last_login','is_active')
This seems to solve it by altering the filename and deleting the existing file prior to the form save.
form = MemberProfileForm(request.POST, request.FILES, instance=request.member)
if form.is_valid():
if form.cleaned_data['image']:
(path, extension) = os.path.splitext(form.cleaned_data['image'].name)
form.cleaned_data['image'].name = ('%s%s' % (request.member.id, extension))
request.member.image.delete()
form.save()
… excepting that most people probably want ‘request.user’, where I have ‘request.member’.
Date formats are something that US dominance remains unable to overcome. Whilst all software assumes a format of mm/dd/yyyy, all other nations of the world want to change that to their local preference.
Django is no exception.
Here’s the magic incantation to make Django 1.1 output and input dates in an Australian format.
DATE_FORMAT = '%d/%m/%Y'
...
class ProfileForm(forms.ModelForm):
...
date_of_birth = forms.DateField()
date_of_birth.widget = forms.DateInput(format=DATE_FORMAT)
date_of_birth.input_formats = (DATE_FORMAT,)
Given someone’s date of birth how do I work out their age? This is actually less trivial than first appears because:
- the person’s age doesn’t increment until their birthday passes on the calendar
- that day is not always the same period of time after midnight on the 1st of January
This solution works by asking if today’s month is before their birthday, and if their birthday is this month whether today’s date is before the birth day.
This works even if they are born on the 29th of Feb.
def age(dob):
import datetime
today = datetime.date.today()
if today.month < dob.month or \
(today.month == dob.month and today.day < dob.day):
return today.year - dob.year - 1
else:
return today.year - dob.year
>>> import datetime
>>> datetime.date.today()
datetime.date(2009, 12, 1)
>>> age(datetime.date(2008, 11, 30))
1
>>> age(datetime.date(2008, 12, 1))
1
>>> age(datetime.date(2008, 12, 2))
0
Recent Comments