yourlabs / django-autocomplete-light

A fresh approach to autocomplete implementations, specially for Django. Status: v4 alpha, v3 stable, v2 & v1 deprecated.
https://django-autocomplete-light.readthedocs.io
MIT License
1.8k stars 467 forks source link

catch ValueError if selected_choices are invalid #1321

Closed shapiromatron closed 1 year ago

shapiromatron commented 1 year ago

Users may craft an invalid choice, for example, entering a string where an integer based ID is expected, and this would result in a ValueError when trying to render the field in a django template.

This PR catches cases where an the choices are invalid and silently continues. You could also set the queryset of choices to be empty, but this was a less disruptive (though perhaps harder to debug) option.

This fixes errors like those below, if a user manually sets a value like abc where an integer-based ID is expected:

  File "../dal/widgets.py", line 187, in filter_choices_to_render
    qs = self.choices.queryset.filter(pk__in=[c for c in selected_choices if c])
  File "../django/db/models/query.py", line 941, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "../django/db/models/query.py", line 961, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "../django/db/models/query.py", line 968, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "../django/db/models/sql/query.py", line 1416, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "../django/db/models/sql/query.py", line 1435, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "../django/db/models/sql/query.py", line 1370, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "../django/db/models/sql/query.py", line 1216, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "../django/db/models/lookups.py", line 25, in __init__
    self.rhs = self.get_prep_lookup()
  File "../django/db/models/lookups.py", line 240, in get_prep_lookup
    rhs_value = self.lhs.output_field.get_prep_value(rhs_value)
  File "../django/db/models/fields/__init__.py", line 1825, in get_prep_value
    raise e.__class__(
ValueError: Field 'id' expected a number but got 'abc'.
jpic commented 1 year ago

Thank you for your contribution! Released in 3.9.5-rc6 :tophat:

shapiromatron commented 1 year ago

thank you! great project!!