WayBehind
WayBehind

Reputation: 1697

Django Forms - Format Select Field Time Value as AM/PM

I have a Django form select field with 15 min time slot options:

<select id="mytime" name="mytime">
<option value="2:00 PM">2:00 PM</option>
<option value="2:15 PM">2:15 PM</option>
<option value="2:30 PM">2:30 PM</option>
<option value="2:45 PM">2:45 PM</option>
...

The problem I have is that when I'm editing the instance values, the current time value will not be automatically selected unless I have the option values in 24h format such as <option value="14:45:00">14:45:00</option> as that is the matching database format.

views.py

times = []
for i in range(0, 24*4):
    times.append((datetime.combine(date.today(), time()) + timedelta(minutes=15) * i).time().strftime("%I:%M %p").lstrip('0'))
form = MyForm(instance=instance, 
       options=[( choice, choice ) for choice in times])
return ...

forms.py

self.fields['mytime'] = forms.ChoiceField(
                        required=True,
                        choices=options,
                        widget=forms.Select(
                            attrs={'class': 'myclass',}
                       ))

As this is a Select field, the widget will not accept the format attribute.

Any way around this?

How can I achieve AM/PM format in my drop down menu with the current value selected?


Working code:

forms.py

def __init__(self, *args, **kwargs):
options = kwargs.pop('options', None)
super(MyForm, self).__init__(*args, **kwargs)

self.fields['mytime'] = forms.ChoiceField(
                        required=True,
                        choices=options,
                        widget=forms.Select(
                            attrs={'class': 'myclass',}
                       ))

view.py

 form = MyForm(request.POST or None, instance=instance,
                   options=[( choice.strftime("%H:%M:%S"), choice.strftime("%I:%M %p").lstrip('0') ) for choice in times])

Upvotes: 1

Views: 1256

Answers (2)

sthzg
sthzg

Reputation: 5554

If I understand you correctly, everything would work if the markup looked like this

<option value="14:00:00">2:00 PM</option>

You could change views.py so that it generates the choices tuple with a value in 24h-format and a display string with a.m. and p.m.

times = []
for i in range(0, 24*4):
    times.append((datetime.combine(date.today(), time()) + timedelta(minutes=15) * i).time())
form = MyForm(instance=instance,
       options=[( choice.strftime("%H:%M:%S"), choice.strftime("%I:%M %p").lstrip('0') ) for choice in times])
return ...

Upvotes: 4

Iain Shelvington
Iain Shelvington

Reputation: 32244

This can be achieved by passing the parameter initial.

Something similar to the following should do the trick

if instance:
    mytime_initial = time.strptime(instance.mytime, '%I:%M %p').lstrip('0')
else:
    mytime_initial = None

self.fields['mytime'] = forms.ChoiceField(
    required=True,
    choices=options,
    initial=mytime_initial,
    widget=forms.Select(
        attrs={'class': 'myclass',}
    )
)

Upvotes: 2

Related Questions