django-autocomplete-light
django-autocomplete-light copied to clipboard
Why do you use the label text for the select2 option value and not the pk id?
Why do you use the label text for the select2 option value and not the pk id? If someone wants to use the label for the option value, he can simply set {"id": self.q, "label": self.q} from the serverside before the POST response.
https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/static/autocomplete_light/select2.js#L92
It is just for tags: https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/static/autocomplete_light/select2.js#L90
I think I use tags by setting my widget to autocomplete.ModelSelect2Multiple() and subclassing autocomplete.Select2QuerySetView() in views.py.
When I change #L92 from value.id = value.text; to value.id = value.id;
then it correctly uses the pk id for the GET request variables, else it uses the label.
Why should tags use the label text for their select2 option value? Is it the correct behavior to use the label for the tags' option value?
I think that is because tags allow approximation search, so if you have in your backend "John Doe" and just type in "John", then you can still get a result by filtering for icontains="John", so if the javascript would instead only accept the pk id, you couldn't do that sort of approximation filtering.
But you can still just overwrite:
def get_result_value(self, result):
"""Return the value of a result."""
return str(result.title)
So I still wonder why not using value.id = value.id in javascript? :-)
It's probably for backward compatibility story. Django tagging apps solve the issue "use a text input and provide a model field to encapsulate a generic many to many relation". They provide the tag model field or manager to handle this conversion between text input and a generic multiple relation. This special use case is supported with specific widget class TagSelect2, which also supports the specific use case of select2 in tagging mode. Probably, the form fields were expecting tag names instead of primary keys, hence this serie of hacks.
What kind of tag model and relation are you using ?
I don't use a tagging model, that may explain my issue. I simply used a normal model
models.py
class Persons(models.Model): name = models.CharField(max_length=128, unique=False, blank=True)
views.py
class TitleAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Persons.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q).order_by("name")
return qs
def get_result_value(self, result):
"""Return the value of a result."""
return str(result.name)
And then monkeypatched
apps.py
def filter_choices_to_render2(self, selected_choices): """Filter out un-selected choices if choices is a QuerySet.""" if "persons/title-autocomplete2/" in self.url: choices_pk = [] choices_text = [] for x in selected_choices: if is_number(x): choices_pk.append(x) else: choices_text.append(x) self.choices.queryset = self.choices.queryset.filter( Q(pk__in=[c for c in choices_pk if c]) | Q(name__in=[c for c in choices_text if c]) | Q(original_name__in=[c for c in choices_text if c]) )
class MyAppConfig(AppConfig): name = "persons"
def ready(self):
QuerySetSelectMixin.filter_choices_to_render = filter_choices_to_render2
Maybe converting my model field to a tagging field would make my patches redundant.
Please try to reproduce your issue in an example app in the test project and reopen this issue
Hi,
I think this issue should be reopened. I got crazy with this issue, but I think is a bug.
For "new options" you use "id" to save the "tag string" (see code line) and as "text" you set "Create XXXX".
So when you use data-tags, "id" becomes "Create XXXX" (see code line) and that is what is used to create new options (see code line).
This actually could be fixed overriding get_create_option of Select2ViewMixin and changing the "text" value, but because of that issue, when you submit the form, texts are sent as values, instead of ids...
Can you show an example patch that works for you ?
Hi, actually I couldn't make it works...
Ok, could you reproduce your issue in test project? It would be easier to take a look on a live example I can debug