DropDown field not getting assigned with datalist values on selection

Though the datalist displays the list of values, upon selection from the form the value is not getting stored/assigned to the field which in turn not getting saved to the DB. Below are the setup. Request help on the same. - Thank you!

The field ‘State’ is linked with list of values from the model ‘State’ which though displays the list of values, upon selection and submitting the form the value disappears and error throws upon.

Portion of html file:

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

related view in views.py,

def create(request):
    form = EmployeeMForm()
    StateList = State.objects.all()

    if request.method == 'POST':
        form = EmployeeMForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('employeem-list')

    context = {
        'StateList': StateList,
        'form': form,
    }
    return render(request,'EmployeeM/create1.html', context)

respective models:

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):
    id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
    Name = models.CharField(max_length=200)
    Email = models.EmailField()
    Contact = models.CharField(max_length=20)
    Role = models.CharField(max_length=200)
    Salary = models.IntegerField() 
    State = models.ForeignKey(State,on_delete=models.SET_NULL,null=True)
    JoinDate = models.DateField()
    ToDate = models.DateField()

    def __str__(self):
        return self.Name

respective forms.py

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

        fields = ('Name', 'Email', 'Contact', 'Role', 'Salary', 'State', 'JoinDate', 'ToDate')

        labels = {
                  'JoinDate':'Join Date',
                  'ToDate':'Last Date',
                  }

        widgets = {
            'Name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Name', 'style': 'width: 400px', 'style': 'height: 30px'}),
            'Email': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Email', 'style': 'width: 400px'}),
            'Contact': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Contact No.', 'style': 'width: 400px'}),
            'Role': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Role', 'style': 'width: 400px'}),
            'Salary': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Salary', 'style': 'width: 400px'}),
            'State': forms.Select(attrs={'class': 'form-control', 'placeholder': 'State', 'style': 'width: 400px'}),
            'JoinDate': forms.DateInput(attrs={'type':'date', 'class': 'form-control', 'placeholder': 'Join date', 'style': 'width: 400px'}),
            'ToDate': forms.DateInput(attrs={'type':'date', 'class': 'form-control', 'placeholder': 'Last date', 'style': 'width: 400px'}),
        }

The issue here is that you are not rendering the State field in the form. You’re creating the State widget in your form, but then rendering an input field directly.

Thanks Ken!
I corrected forms.py as below. Still no effect. The selected value is not getting assigned to the field and so not able to save the form. Any help please?

class EmployeeMForm(forms.ModelForm):
    State = forms.ModelChoiceField(queryset=State.objects.all(), empty_label="(Nothing)", to_field_name='StateName')

    class Meta:
        model = EmployeeM

        fields = ('Name', 'Email', 'Contact', 'Role', 'Salary', 'State', 'JoinDate', 'ToDate')

        labels = {
                  'JoinDate':'Join Date',
                  'ToDate':'Last Date',
                  }

        widgets = {
            'Name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Name', 'style': 'width: 400px', 'style': 'height: 30px'}),
            'Email': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Email', 'style': 'width: 400px'}),
            'Contact': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Contact No.', 'style': 'width: 400px'}),
            'Role': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Role', 'style': 'width: 400px'}),
            'Salary': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Salary', 'style': 'width: 400px'}),
            'JoinDate': forms.DateInput(attrs={'type':'date', 'class': 'form-control', 'placeholder': 'Join date', 'style': 'width: 400px'}),
            'ToDate': forms.DateInput(attrs={'type':'date', 'class': 'form-control', 'placeholder': 'Last date', 'style': 'width: 400px'}),
        }

It’s not that you needed to remove the State widget from the form, it’s that you need to render the State widget in the template.

Thank you very much Ken!!

Did add the attribute ‘name’ in the input tag and got it worked. following is the updated template code,

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

You’re still not rendering this as a form field - you’re still manually rendering the input element. Which will work, but can become a maintenance issue down the road. (It’s a practice I never recommend) You really should be rendering this as {{ form.State }}.

Also be aware that the datalist does not need to be near the element(s) using it in the page, and that a single datalist can be used by multiple elements.

When I use {{ form.Sate }} the value disappears upon saving. :expressionless: Could you please guide how to use the form field? Below is the code I did change as per your last reply and the issue with the form on runserver.

                <tr>
                    <th>{{ form.State.label_tag }}</th>
                    <td>
                        {{ form.State.errors }} 
                        <input autoComplete="on" list="States" placeholder="State" type="text" class="form-control" name="State" />
                        <datalist id="States">

                            {{ form.State }}
                             
                        </datalist> 
                    </td>
                </tr>


Two problems.

  1. You’ve got both your manually-created input element and the form.State element

  2. You’ve got form.State inside your datalist.

This is just like any other form field.

If necessary, review Working with forms | Django documentation | Django

Yes, I need that datalist for autocomplete feature, which isn’t there in form field. So, this solution won’t work?

That’s fine. But the data list is a separate html element from the input element. The two are only related by name.