问题描述
我正在构建一个需要通过输入以下两个属性之一来搜索特定用户记录的 Web 应用程序:名字或姓氏。最终会有两个更多的搜索属性,但目前在同一个模板中有两个 autocomplete-light 下拉菜单有问题。问题是只有第二个下拉菜单按预期工作。
以下是相关代码部分(删除了无关代码)。这种方法不是“DRY”,但我的首要任务是在优化/重构之前有一个有效的实现。
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'),**kwargs):
super(StudentChoiceFieldFN,**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'),...
]
奖项/index.html
注意下方 {{ Students_choice_fn.media }} 声明的位置。根据其他相关堆栈溢出帖子中的建议,我尝试将此声明的位置更改为模板的不同部分。我认为问题与 autocomplete-light 的相关 css/javascript 的渲染有关,以某种方式导致第一个字段无法正常工作。
{% 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 %}
问题是只有第二个自动完成下拉列表有效,第一个下拉列表显示为空的非交互式下拉列表。在此处查看屏幕截图:
这是两个概念重叠的线程,但我无法解决我的问题:
How to use django-autocomplete-light on form with multiple charfields
https://github.com/yourlabs/django-autocomplete-light/issues/814
感谢您的帮助!
解决方法
由于两个表单在同一个表单标签中,所以在渲染的 html 中为它们分配了相同的 id。
<form method=POST action="/awards/select">
{% csrf_token %}
{{ students_choice_ln }}
{{ students_choice_fn }}
<input type="submit" value="select">
</form>
按照此处记录的说明 (https://docs.djangoproject.com/en/dev/ref/forms/api/#prefixes-for-forms) 操作后,下拉菜单按预期工作。可能是匹配的 id 阻止了 javascript/css 链接正常工作。