Django: Rendering display value of a ModelChoiceField and ChoiceField in a template - django

I have a ModelChoiceField and a ChoiceField that I need to pull out the "display name" for (not the "value").
For example, a ModelChoiceField of a form renders the following output:
<select name="amodelfield" id="id_amodelfield">
<option value="">---------</option>
<option selected="selected" value="1">ABC</option>
<option value="2">DEF</option>
</select>
I want to be able to just render "ABC" since it is selected. If I do {{ field.value }} as said in the docs, I get the value 1 instead of the ABC I wanted. I also have a ChoiceField for which I want the same behavior.
Is there a easy way to do this without subclassing ModelChoiceField, ChoiceField and the Select widget?
EDIT: Model.get_FOO_display() would not work in this case

Use {{ get_fieldname_display }} for it.
https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display

From the link that #Odif Yltsaeb provided, I was able to use modify the code from the answer to work generically for my needs. Here's the code for reference:
def choiceval(boundfield):
"""
Get literal value from field's choices. Empty value is returned if value is
not selected or invalid.
Important: choices values must be unicode strings.
choices=[(u'1', 'One'), (u'2', 'Two')
Modified from:
https://stackoverflow.com/a/5109986/2891365
Originally found from:
https://stackoverflow.com/questions/19960943/django-rendering-display-value-of-a-modelchoicefield-and-choicefield-in-a-templ
"""
# Explicitly check if boundfield.data is not None. This allows values such as python "False"
value = boundfield.data if boundfield.data is not None else boundfield.form.initial.get(boundfield.name)
if value is None:
return u''
if not hasattr(boundfield.field, 'choices'):
return value
return dict(boundfield.field.choices).get(value, u'')

Related

get selected value in clean form

Trying to write custom validation for select field in the form. in template orm is displayed as:
<select id="id_myselect" name="myselect">
<option value="" selected="selected">---------</option>
<option value="1">First</option>
<option value="2">Second</option>
</select>
forms.py
class SubmitForm(forms.ModelForm):
...
def clean_myselect(self):
data=self.cleaned_data['myselect']
if data == 'First':
do something
return data
Doesn't work I'm also try to get error on the page and I see that value is on the page.
Request information POST myselect u'1' but Local vars say value myselect <Myselect: First> Any help?
You need to compare on the data value of the select not the sting.
As you have pointed out the value for myselect is u'1' so you need to compare against that and not the string representation.
class SubmitForm(forms.ModelForm):
...
def clean_myselect(self):
data=self.cleaned_data['myselect']
if data == 1: # 1 not "First"
do something
return data

Datetime values in Django forms (initial and submitted has different format thought)

For some reason I use a custom HTML-code for displaying the form. My form's input get the initial value (date), and shows the same form after submittion.
But after submit, input has no previously selected value (just empty).
I use {{ Form.Fileld.value|date:"Y-m-d" }} in the temlate to get initial and submitted values.
It seems that initial and submitted values are in different formats: "datetime" for initial values and "string" after submit.
Here is my simple test:
Form
class ShowStartEndDateForm(forms.Form):
start_date = forms.DateField(initial=date.today().replace(day=1),
label="Start",
widget=forms.DateInput(format='%Y-%m-%d'),
input_formats=['%Y-%m-%d'])
...
View
if request.method == 'POST':
form_date = ShowStartEndDateForm(request.POST)
if form_date.is_valid():
form_was_submitted = True
cd = form_date.cleaned_data
operator = cd['operators']
days=[]
for day in range(0,(cd['end_date']-cd['start_date']).days+1):
days.append(cd['start_date']+relativedelta(days=+day))
else:
form_date = ShowStartEndDateForm()
return render_to_response('epay.html', locals(),
context_instance=RequestContext(request))
Template
<!- HTML FORM here
|classname is my custom template filter.
-->
Date1: {{ form_date.start_date.value|date:"Y-m-d" }} \
({{ form_date.start_date.value|classname }})
Date2: {{ form_date.start_date.value }}
First call in browser:
Date1: 2013-10-01 (date)
Date2: 1 October 2013
After form submit:
Date1: (unicode)
Date2: 2013-10-01
What am I doing wrong? What is the proper way to access form's field initial and submitted values?
Thnak you.
You're question is a bit confusing (you should add some more of your actual code), but I know from experience that when mixing between formats, its a good convention to just do it all in one place. So instead of specifying the format on the client side like you do, specify it all on the form itself and then everything would (should) be in-sync.
class ShowStartEndDateForm(forms.Form):
start_date = forms.DateField(initial=date.today().replace(day=1),
label="Start",
widget=DateInput(format='%Y-%m-%d'),
input_formats=['%Y-%m-%d'])
i.e. you tell the the DateInput widget what form to take and you tell input_formats (for the field itself) what formats to expect (you can add more than one). Also, if you are using some sort of datepicker you of course need to make sure it is also using the right format.
Edit
I replicated this and everything was fine:
In [1]: from test.forms import *
In [2]: f = ShowStartEndDateForm()
In [3]: print f
<tr>
<th><label for="id_start_date">Start:</label></th>
<td><input id="id_start_date" name="start_date" type="text" value="2013-10-01" /></td>
</tr>
(of course I changed the indentation here so you could see it more clearly)

Django forms: checkboxes are displayed without value

I'm unable to save my form (a ModelForm) properly, since django displays checkboxes without a value (I would expect value="true" on every fields, both checked than unchecked... but that's not the case).
When I submit the form, no data is received in the POST!
The following is a piece o my template:
<div>
{{form.displayAge.label_tag}}
{{form.displayAge}}
{{form.displayAge.errors}}
</div>
{{form.displayAge}} is rendered in this way:
<input checked="checked" type="checkbox" name="displayAge" id="id_displayAge">
BUT... since it has no value, checking/unchecking the checkbox is helpless! What should I do?
I would like to avoid typing form fields by hand!
No, there is no need for a value field. If the checkbox is checked, the browser will submit "on" as the value by default if none is supplied.
If you're not getting this value in your view, something else is wrong. Note that since you're using Django forms, you shouldn't be checking request.POST manually anyway: use form.cleaned_data.

Django ChoiceField get currently selected

I have a simple ChoiceField and want to access the 'selected' item during my template rendering.
Lets say the form gets show again (due to error in one of the fields), is there a way to do something like:
<h1> The options you selected before was # {{ MyForm.delivery_method.selected }} </h1>
(.selected() is not working..)
Thanks !
#Yuji suggested bund_choice_field.data, however that will return value which is not visible to user (used in value="backend-value"). In your situation you probably want literal value visible to user (<option>literal value</option>). I think there is no easy way to get literal value from choice field in template. So I use template filter which does that:
#register.filter(name='choiceval')
def choiceval(boundfield):
"""
Get literal value from field's choices. Empty value is returned if value is
not selected or invalid.
Important: choices values must be unicode strings.
choices=[(u'1', 'One'), (u'2', 'Two')
"""
value = boundfield.data or None
if value is None:
return u''
return dict(boundfield.field.choices).get(value, u'')
In template it will look like this:
<h1> The options you selected before was # {{ form.delivery_method|choiceval }} </h1>
UPDATE: I forgot to mention an important thing, that you will need to use unicode in choice values. This is because data returned from form is always in unicode. So dict(choices).get(value) wont work if integers where used in choices.
It would be accessed by {{ myform.delivery_method.data }}
<h1> The options you selected before was # {{ MyForm.delivery_method.data }} </h1>

Get Value Of Selected Option ModelChoiceField

Without using Ajax is there a way to get the value of a selected item. So for example, if I have the below drop down list:
<select name="controllers" id="id_controllers">
<option value="" selected="selected">---------</option>
<option value="1">http://przemeklach.com/api/firstOrder/przemeksController</option>
<option value="5">http://przemeklach.com/api/zeroOrder/ronsController</option>
</select>
How would I get at the 'value' in my view. I know I can get the 'http://przemeklach.com/api/firstOrder/przemeksController' part via
controller = form.cleaned_data['controllers']
but I also need the 'value' in this case 1.
Thanks.
Scratch the old response (below), cleaned_data contains object references. You can get the ID by refering to model methods.
You can get the id from form.data['controllers'] but it needs sanity checking (in this case it should be an int). Of course if the is_valid() returns True it should be one of the ids available in the queryset you supplied when defining the field.