I am building a web application that requires searching for a specific user record by entering one of two attributes: first name OR last name. Eventually there will be two more search attributes, but currently having problems with having two autocomplete-light drop-downs in the same template. The problem is that only the second drop-down is working as expected.
Below are the relevant code sections (with irrelevant code removed). This approach is not "DRY" but my priority is to have a working implementation before optimization/refactoring.
forms.py
class StudentChoiceFieldLN(forms.Form):
students = forms.ModelChoiceField(
queryset=Student.objects.all().order_by("last_name"),
widget=autocomplete.ModelSelect2(url='student-ln-autocomplete'),
)
def __init__(self, *args, **kwargs):
super(StudentChoiceField, self).__init__(*args, **kwargs)
# without the next line label_from_instance does NOT work
self.fields['students'].queryset = Student.objects.all().order_by("last_name")
self.fields['students'].label_from_instance = lambda obj: "%s %s" % (obj.last_name, obj.first_name)
class StudentChoiceFieldFN(forms.Form):
students = forms.ModelChoiceField(
queryset=Student.objects.all().order_by("first_name"),
widget=autocomplete.ModelSelect2(url='student-fn-autocomplete'),
)
def __init__(self, *args, **kwargs):
super(StudentChoiceFieldFN, self).__init__(*args, **kwargs)
# without the next line label_from_instance does NOT work
self.fields['students'].queryset = Student.objects.all().order_by("first_name")
self.fields['students'].label_from_instance = lambda obj: "%s %s" % (obj.last_name, obj.first_name)
views.py
class StudentLNAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Student.objects.all()
if self.q:
qs = qs.filter(last_name__istartswith=self.q)
return qs
class StudentFNAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Student.objects.all()
if self.q:
qs = qs.filter(first_name__istartswith=self.q)
return qs
def index(request):
students_choice_ln = StudentChoiceFieldLN()
students_choice_fn = StudentChoiceFieldFN()
context = {
'students_choice_ln': students_choice_ln,
'students_choice_fn': students_choice_fn,
'selected_student': None
}
return render(request, 'awards/index.html', context)
urls.py
from awards.views import StudentLNAutoComplete
from awards.views import StudentFNAutoComplete
urlpatterns = [
...
path('student-ln-autocomplete/', StudentLNAutoComplete.as_view(), name='student-ln-autocomplete'),
path('student-fn-autocomplete/', StudentFNAutoComplete.as_view(), name='student-fn-autocomplete'),
...
]
awards/index.html
Note below the position of the {{ students_choice_fn.media }} declaration. Based on recommendations found in other related stack overflow posts, I tried changing the location of this declaration to different parts of the template. I think the problem is related to the rendering of the relevant css/javascript for autocomplete-light, somehow causing the first field to not work correctly.
{% extends "base.html" %}
{% block content %}
<body>
{{ students_choice_fn.media }}
<div class="container">
<div class="row">
<div class="col-md-6">
<form method=POST action="/awards/select">
{% csrf_token %}
{{ students_choice_ln }}
{{ students_choice_fn }}
<input type="submit" value="select">
</form>
<br>
<h4> {{ selected_student.first_name }} {{ selected_student.last_name }} </h4>
{% if selected_student %}
....
{% endif %}
</div>
<div class="col-md-6">
....
</div>
</div>
</div>
</body>
{% endblock %}
The problem is that only the second autocomplete dropdown is working, and the first dropdown displays as an empty non-interactive dropdown. See screenshot here:
These are two threads with overlapping concepts, but I was not able to resolve my problem:
How to use django-autocomplete-light on form with multiple charfields
https://github.com/yourlabs/django-autocomplete-light/issues/814
I appreciate your help!