Joe
Joe

Reputation: 43

Django - ModelChoiceField empty choice missing

Django docs say when using ModelChoiceField on a form and form is set to required=False and model is set to blank=True in addition to no default values, then I should receive a free empty choice within my select tag. I am not. Any ideas to what I've done to lose the empty choice?

models.py

class Location(models.Model):
    location_name = models.CharField(max_length=50, blank=True)
    address = models.CharField(max_length=50)
    active = models.BooleanField(default=True)

    def __unicode__(self):
        return self.location_name

forms.py

class CalcForm(forms.Form):
    startAddr = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
    waypoint1 = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
    waypoint2 = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
    ...
    endAddr = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)

template.html

<form action="../calcview" method="get">{% csrf_token% }
<label>
    <div>Start Address</div>
    <select name="startAddr">
        {% for location in form.fields.startAddr.queryset %}
            <option value = "{ location.location_name }">{{location.location_name}}/option>
        {% end for %}
    </select>
...
</form>

Upvotes: 3

Views: 8135

Answers (3)

Greatxam Darthart
Greatxam Darthart

Reputation: 188

You can use the empty_label on your ModelChoiceField.

startAddr = forms.ModelChoiceField(empty_label='---------', queryset=Location.objects.all(), required=False)

Then render the form field into the template.

{{ form.startAddr }}

https://docs.djangoproject.com/en/2.1/ref/forms/fields/#django.forms.ModelChoiceField.empty_label

Upvotes: 4

goetz
goetz

Reputation: 684

I know, you asked more than half a year ago, but I thought I post another answer anyway. Because I think there is a more elegant solution that uses the "empty_label" that you can define in your form.

You can access this empty_label attribute through form.fields.startAddr.empty_label or form.startAddr.field.empty_label in your template. So you can include it like this:

<select id="{{ form.fields.startAddr.id_for_label }}" name="{{ form.fields.startAddr.html_name }}">
    <option value="">{{ form.fields.startAddr.empty_label }}</option>
    {% for location in form.fields.startAddr.queryset %}
        <option value="{{ location.location_name }}">{{ location.location_name }}/option>
    {% endfor %}
</select>

I wonder if you did not actually want to use {{ location.id }} as value? Or is the location_name unique? As it could even be empty, the auto-generated id might be better as a reference.

As you can see, I have also replaced name="startAddr" with information the form object provides anyway for every field: id="{{ form.fields.startAddr.id_for_label }}" name="{{ form.fields.startAddr.html_name }}. Using these variables should make your template code more flexible and robust.

For more details, please check the Django documentation:

Upvotes: 1

dgel
dgel

Reputation: 16806

You will only get the 'free' empty option if you allow django forms to render the form field automatically. Because you are rendering it yourself in your template (and I don't know why you would want to do that...) you would need to add the empty select yourself:

<select name="startAddr">
    <option value="">-----------</option>
    {% for location in form.fields.startAddr.queryset %}    
        <option value = "{ location.location_name }">{{location.location_name}}</option>
    {% end for %}
</select>

You can test this by allowing django form to render it for you:

<div>Start Address</div>
{{ form.startAddr }}

Upvotes: 5

Related Questions