From the docs,
class CountryAutocompleteFromList(autocomplete.Select2GroupListView):
def get_list(self):
return [
("Country", ['France', 'Fiji', 'Finland', 'Switzerland'])
]
Can we supply value and text tuple, like so
I tried but not happening.
class CountryAutocompleteFromList(autocomplete.Select2GroupListView):
def get_list(self):
return [
("Country", [('france','France'),('fiji','Fiji'), ('finland','Finland'),( 'switzerland','Switzerland')])
]
Apparently not yet supported: https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py#L150
Pull request welcome ;)
Perhaps overriding the results method (along with get_list) may work for you?
https://github.com/yourlabs/django-autocomplete-light/blob/037a83a3c21c425fa271775f56b7d22abd30d373/src/dal_select2/views.py#L98-L100
I have had a problem like this. I wanted to define the value in the <option> tag an not only the text as is done by Select2ListView. So I just adapted this one a bit:
class Select2DictView(autocomplete.Select2ListView):
"""Autocomplete from a dictionary of items rather than a QuerySet."""
def get_dictionary(self):
"""
Return the dictionary from which to autocomplete.
- the key goes to the value attribute of the option tag
- the value is the text enclosed by the option tag
"""
return {}
def get(self, request, *args, **kwargs):
""""Return option list json response."""
results = self.get_dictionary()
create_option = []
if self.q:
results = [x for x in results if self.q.lower() in x.lower()]
if hasattr(self, 'create'):
create_option = [{
'id': self.q,
'text': 'Create "%s"' % self.q,
'create_id': True
}]
return HttpResponse(
json.dumps(
{'results': [dict(id=key, text=value) for key, value in results.items()] + create_option}
),
content_type='application/json'
)
class ExampleAutocompleteByDictView(Select2DictView):
""" returns an equivalent of this html
<select>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">one plus two</option>
</select>
"""
def get_dictionary(self) -> dict:
return {
1: "one",
2: "two",
3: "one plus two"
}
Maybe the author of this awesome Django package could treat my little hacking as a blueprint. This approach of inheritance is definitely not DRY. But with a bit of refoactoring it should get implemented by chance?
if you want to refactor the widget/view part, why not try @Guilouf's pattern with widgets that make views ? it's currently in the gfk widget:
https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2_queryset_sequence/fields.py#L24
https://github.com/yourlabs/django-autocomplete-light/blob/master/test_project/select2_generic_foreign_key/urls.py#L20
if you follow this lead you can acheive dry
@mpibpc-mroose
In 3.3.0-rc* there is a results in Select2ListView which you can override without much boilerplate (thx to @eayin2). If you want to add your DictView, a PR would be welcome.
To resolve this issue, should I create a new field/widget or refactor the existing ones?
I am not a python expert, my solution may not be idyllic.
I resolve the problem just create own class and override get method:
My List:
[('group', ('id', 'value'))]
class Select2GroupListView(autocomplete.Select2GroupListView):
def get(self, request, *args, **kwargs):
""""Return option list with children(s) json response."""
results_dict = {}
results = self.get_list()
if results:
flat_results = [(group, items) for entry in results
for group, items in self.get_item_as_group(entry)]
if self.q:
q = self.q.lower()
flat_results = [(g, x) for g, x in flat_results
if q in x.lower()]
for group, value in flat_results:
results_dict.setdefault(group, [])
results_dict[group].append(value)
return http.HttpResponse(json.dumps({
"results":
[{"id": x, "text": y} for x, y in results_dict.pop(None, [])] +
[{"id": g, "text": g, "children": [{"id": x, "text": y}
for x, y in l]}
for g, l in six.iteritems(results_dict)]
}))
My solution to work with same choices that I put into model field choices attribute.
class Select2TuplesListView(autocomplete.Select2ListView):
def autocomplete_results(self, results):
filtered_results = []
for current_tuple in results:
name = current_tuple[1]
print(name.lower())
if self.q.lower() in name.lower():
filtered_results.append(current_tuple)
return filtered_results
def results(self, results):
"""Return the result dictionary."""
return [dict(id=x[0], text=x[1]) for x in results]
Usage example:
class CityCountryAutocomplete(Select2TuplesListView):
def get_list(self):
return services.get_geoip_cities_choices() # returns list of tuples: [(1, 'a'), (2, 'b') ... ]