Django - Autocomplete dropdown field amidst other fields in a form

1.3k views Asked by At

I am trying to make 1 field in a form an autocomplete dropdown box which lists values from another model, but no success. It is a 'Create' form to feed in employees details. I am new to application developing. So finding difficult in understanding the concepts to implement. Kindly help.

here is my model.

class State(models.Model):
    StateCode = models.CharField(max_length=2)
    StateTIN = models.IntegerField()
    StateName = models.CharField(max_length=100)
    
    def __str__(self):
        return self.StateName

class EmployeeM(models.Model):
    Name = models.CharField(max_length=200)
    Email = models.EmailField() 
    State = models.ForeignKey(State,on_delete=models.SET_NULL,null=True) 
 
     
    def __str__(self):
        return self.Name

Here are the views,

    #Create html view
    def create(request):
        form = EmployeeMForm()
    
        if request.method == 'POST':
            form = EmployeeMForm(request.POST)
            if form.is_valid():
                form.save()
                return redirect('employeem-list')
    
        context = {
            'form': form,
        }
        return render(request,'EmployeeM/create.html', context)



#List States
def state_list(request):
    states = State.objects.all()
    context = {
        'states': states
        }
    return render(request, 'State/statelist.html', context)

Here is my part of HTML codes where I am trying to make the field 'State' as dropdown box as well as searchable.

{% csrf_token %}
{{ form.non_field_errors }}
{{ form.source }}

<table border="1" cellpadding="10px">

    <tr>
        <th>{{ form.Name.label_tag }}</th>
        <td> 
            {{ form.Name.errors }}
            {{ form.Name }}
        </td>
    </tr>
    <tr>
        <th>{{ form.Email.label_tag }}</th>
        <td>
            {{ form.Email.errors }}
            {{ form.Email }}
        </td>
    </tr>
    <tr>
        <th>{{ form.State.label_tag }}</th>
        <td>
            {{ form.State.errors }} 
            <input autoComplete="on"  type="text" list="states" placeholder="State" class="form-control" />
            <datalist id="states">
                {% for s in states %}
                <option value="{{ s.State }}"></option>
                {% endfor %}
            </datalist>
        </td>
    </tr>

Here is my forms.py

class EmployeeMForm(forms.ModelForm):
    class Meta:
        model = EmployeeM

        fields = ('Name', 'Email', 'Contact', 'State')

        widgets = {
            'Name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Name', 'style': 'width: 400px'}),
            'Email': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Email', 'style': 'width: 400px'}),
            'State': forms.Select(attrs={'class': 'form-control', 'placeholder': 'State', 'style': 'width: 400px'}),
        }

But the drop down never appears. Its just displaying an input field. kindly help me to achieve the searchable dropdown box.

Thanks in advance!

1

There are 1 answers

1
sk1p On

You need to pass the "state" model to the template for the cycle to work

def create(request):
        form = EmployeeMForm()
        states = State.objects.all()
        if request.method == 'POST':
            form = EmployeeMForm(request.POST)
            if form.is_valid():
                form.save()
                return redirect('employeem-list')
    
        context = {
            'form': form,
            'states': states
        }
        return render(request,'EmployeeM/create.html', context)

and, I'm not sure, but it seems to me that in the datalist it is not necessary to close the option tag

...
<td>
            {{ form.State.errors }} 
            <input autoComplete="on"  type="text" list="states" placeholder="State" class="form-control" />
            <datalist id="states">
                {% for s in states %}
                <option value="{{ s.StateName }}">
                {% endfor %}
            </datalist>
        </td>
...