Change_form.html cannot display any drop-down select fields for the ModelForm

I'm working on implementing a drop-down menu for the "add" page of Product_to_Stock_Proxy_Admin function in the Django admin interface. The options for the drop-down menu are from the Distributor model, which is a foreign key for the Product model.

The output only shows the drop-down menu itself, and there are no values from the Distributor model, not even the default value "---------". I don't understand why this is happening.

The reason why I use change_form is because I use Ajax to display other columns immediately when the user fills in the barcode_number. Therefore, I need to implement the drop-down menu on my own.

models.py

class Product(models.Model):
    name = models.CharField(max_length=20, blank=True, null=True)
    distributor = models.ForeignKey('Distributor', on_delete=models.CASCADE)
    barcode_number = models.CharField(max_length=20, blank=True, null=True)
    total_amount = models.IntegerField(blank=True, null=True)

class Distributor(models.Model):
    name = models.CharField(max_length=10)

admin.py

class Product_to_Stock_Proxy_Admin(admin.ModelAdmin):
    form = Product_to_Stock_Proxy_Form
    change_form_template = 'admin/change_form.html'

    fields = ["distributor", "name", "total_amount"]

admin/change_form.html

This code only displays the drop-down item itself without any options, not even the default value "-------":

{% block content %}
<form method="post">
    {% csrf_token %}
    {{ form.non_field_errors }}

    <div class="form-row field-barcode_number">
        <div>
            <div class="flex-container">
                <label for="id_barcode_number">條碼號碼:</label>
                <input type="text" id="id_barcode_number" name="barcode_number" value="{{ form.barcode_number.value }}" />
            </div>
        </div>
    </div>

    <div class="form-row field-distributor">
        <div>
            <div class="flex-container">
                <label for="id_distributor">經銷商名稱:</label>
                <select name="distributor" id="id_distributor">
                    {% for distributor in form.field.queryset %}
                        <option value="{{ distributor.id }}">{{ distributor }}</option>
                    {% endfor %}
                </select>
            </div>
        </div>
    </div>

    <div class="form-row field-total_amount">
        <div>
            <div class="flex-container">
                <label for="id_total_amount">總金額:</label>
                <input type="text" id="id_total_amount" name="total_amount" value="{{ form.total_amount.value }}" readonly />
            </div>
        </div>
    </div>

    <button type="submit">submit</button>
</form>
{% endblock %}

forms.py

All the information is printed out in the Anaconda prompt as below:

Initializing form
Queryset set: <QuerySet [<Distributor: David>, <Distributor: John>]>
Form fields: {'barcode_number': <django.forms.fields.CharField object at 0x0000022094F8FD50>, 'distributor': <django.forms.models.ModelChoiceField object at 0x0000022094F8D690>}
class Product_to_Stock_Proxy_Form(forms.ModelForm):
    distributor = forms.ModelChoiceField(queryset=Distributor.objects.all())
    
    class Meta:
        model = Product
        fields = ["distributor", "name", "total_amount"]
       
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print("Initializing form")
        print("Queryset set:", self.fields['distributor'].queryset)
        self.fields['distributor'].widget.attrs.update({'id': 'id_distributor'})
        print("Form fields:", self.fields)

Django Shell Testing

The scripts I run on the Python shell work very well. I try the following:

print(form.fields)
{'distributor': <django.forms.models.ModelChoiceField object at 0x0000020FE7C66450>}
form = Product_to_Stock_Proxy_Form(data={'distributor': 1})
print(form.is_valid())
True
print(form.as_p())
<p>
<label for="id_distributor">Distributor:</label>
<select name="distributor" id="id_distributor" required>
<option value="" selected>---------</option>
<option value="1">David</option>
<option value="2">John</option>
</select>
</p>
print(Distributor.objects.all())
<QuerySet [<Distributor: David>, <Distributor: John>]>

In sum, I think the problem is likely in the template code, as the output from forms.py is normal. The information from the Distributor model is not being passed correctly to the template.

Since I found that the drop-down menu works well in the Django Shell, I revised my admin/change_form.html as follows. However, all I see is nothing; there is no drop-down menu.

{% block content %}
<form method="post">
    {% csrf_token %}
    {{ form.non_field_errors }}
    <div class="form-row field-distributor">
        <div>
            <div class="flex-container">
               {{form.as_p}}
            </div>
        </div>
    </div>
    <button type="submit">submit</button>
</form>
{% endblock %}
{% block content %}
<form method="post">
    {% csrf_token %}
    {{ form.non_field_errors }}
    <div class="form-row field-distributor">
        <div>
            <div class="flex-container">
               {{form.distributor}}
            </div>
        </div>
    </div>
    <button type="submit">submit</button>
</form>
{% endblock %}

The output I want is to have a drop-down menu with the information from the Distributor model.

Back to Top