简体   繁体   中英

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>

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 }}

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM