强制 django-autocomplete=light 到 return 'best' 首先匹配
Force django-autocomplete=light to return 'best' matches first
我有一长串要使用 django-autocomplete-light
字段搜索的项目,自动完成定义如下:
class OccupationAutocomplete(autocomplete_light.AutocompleteModelBase):
model = models.Occupation
search_fields=['title',]
有些职位在列表中按字母顺序排列很远,例如:
"teacher"
在其他 'less ideal titles' 之后,例如:
"Agricultural teacher", "Architecture teacher", "Building teacher", etc...
我想要的是 "best" 匹配,最接近或仅以搜索文本开头的匹配,因此如果有人搜索 "teach",他们会得到 "teacher", 因为它以相同的字母开头,然后是其他不太准确的匹配项。
我试过用首选顺序设置 search_fields
search_fields=['^title','title',]
但对 autocomplete code 的分析表明,这些术语在返回之前都被合并到一个查询中。
我该如何以更合适的方式排序此列表?
最后我不得不实现一个新的 class,它只接受按 'preferred weight' 顺序排列的字典列表,然后 returns 基于它的结果。
class OrderedAutocomplete(autocomplete_light.AutocompleteModelBase):
ordered_search_fields = []
def choices_for_request(self):
"""
Return a queryset based on :py:attr:`choices` using options
:py:attr:`split_words`, :py:attr:`search_fields` and
:py:attr:`limit_choices`.
"""
assert self.choices is not None, 'choices should be a queryset'
q = self.request.GET.get('q', '')
exclude = self.request.GET.getlist('exclude')
base_split_words = self.split_words
_choices = []
for weight,opt in enumerate(self.ordered_search_fields):
if len(_choices) >= self.limit_choices:
break
search_fields = opt['search_fields']
self.split_words = opt['split_words'] or base_split_words
conditions = self._choices_for_request_conditions(q,
search_fields)
choices = self.order_choices(self.choices.filter(conditions).exclude(pk__in=exclude))
if choices.count():
_choices += list(choices)[0:self.limit_choices]
return _choices[0:self.limit_choices]
然后可以使用以下方法实例化:
class OccupationAutocomplete(OrderedAutocomplete):
model = models.Occupation
ordered_search_fields = [
{'search_fields': ['^title'], 'split_words':False},
{'search_fields': ['title'], 'split_words':True},
]
autocomplete_light.register(OccupationAutocomplete)
我有一长串要使用 django-autocomplete-light
字段搜索的项目,自动完成定义如下:
class OccupationAutocomplete(autocomplete_light.AutocompleteModelBase):
model = models.Occupation
search_fields=['title',]
有些职位在列表中按字母顺序排列很远,例如:
"teacher"
在其他 'less ideal titles' 之后,例如:
"Agricultural teacher", "Architecture teacher", "Building teacher", etc...
我想要的是 "best" 匹配,最接近或仅以搜索文本开头的匹配,因此如果有人搜索 "teach",他们会得到 "teacher", 因为它以相同的字母开头,然后是其他不太准确的匹配项。
我试过用首选顺序设置 search_fields
search_fields=['^title','title',]
但对 autocomplete code 的分析表明,这些术语在返回之前都被合并到一个查询中。
我该如何以更合适的方式排序此列表?
最后我不得不实现一个新的 class,它只接受按 'preferred weight' 顺序排列的字典列表,然后 returns 基于它的结果。
class OrderedAutocomplete(autocomplete_light.AutocompleteModelBase):
ordered_search_fields = []
def choices_for_request(self):
"""
Return a queryset based on :py:attr:`choices` using options
:py:attr:`split_words`, :py:attr:`search_fields` and
:py:attr:`limit_choices`.
"""
assert self.choices is not None, 'choices should be a queryset'
q = self.request.GET.get('q', '')
exclude = self.request.GET.getlist('exclude')
base_split_words = self.split_words
_choices = []
for weight,opt in enumerate(self.ordered_search_fields):
if len(_choices) >= self.limit_choices:
break
search_fields = opt['search_fields']
self.split_words = opt['split_words'] or base_split_words
conditions = self._choices_for_request_conditions(q,
search_fields)
choices = self.order_choices(self.choices.filter(conditions).exclude(pk__in=exclude))
if choices.count():
_choices += list(choices)[0:self.limit_choices]
return _choices[0:self.limit_choices]
然后可以使用以下方法实例化:
class OccupationAutocomplete(OrderedAutocomplete):
model = models.Occupation
ordered_search_fields = [
{'search_fields': ['^title'], 'split_words':False},
{'search_fields': ['title'], 'split_words':True},
]
autocomplete_light.register(OccupationAutocomplete)