django-autocomplete-light icon indicating copy to clipboard operation
django-autocomplete-light copied to clipboard

Why do you use the label text for the select2 option value and not the pk id?

Open eayin2 opened this issue 8 years ago • 10 comments
trafficstars

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

eayin2 avatar Aug 27 '17 20:08 eayin2

It is just for tags: https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/static/autocomplete_light/select2.js#L90

jpic avatar Aug 28 '17 14:08 jpic

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?

eayin2 avatar Aug 29 '17 14:08 eayin2

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? :-)

eayin2 avatar Aug 29 '17 20:08 eayin2

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 ?

jpic avatar Aug 29 '17 22:08 jpic

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.

eayin2 avatar Aug 30 '17 17:08 eayin2

Please try to reproduce your issue in an example app in the test project and reopen this issue

jpic avatar Mar 27 '18 21:03 jpic

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...

bilua-xiaolei avatar Nov 21 '19 16:11 bilua-xiaolei

Can you show an example patch that works for you ?

jpic avatar Nov 22 '19 12:11 jpic

Hi, actually I couldn't make it works...

bilua-xiaolei avatar Nov 22 '19 12:11 bilua-xiaolei

Ok, could you reproduce your issue in test project? It would be easier to take a look on a live example I can debug

jpic avatar Dec 04 '19 21:12 jpic