From 58fe85cb7919acbff7b5852e73944b5aa870d032 Mon Sep 17 00:00:00 2001 From: ERIC OUMA Date: Thu, 2 May 2024 16:35:34 +0300 Subject: [PATCH] fix invalid lookup params (#87) --- django_typesense/changelist.py | 45 +++++++++++++++------------------ django_typesense/collections.py | 10 +++++--- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/django_typesense/changelist.py b/django_typesense/changelist.py index 11d23a6..3a15862 100644 --- a/django_typesense/changelist.py +++ b/django_typesense/changelist.py @@ -427,31 +427,26 @@ def get_queryset(self, request): if new_qs is not None: qs = new_qs - lookup_params_keys = remaining_lookup_params.keys() - model_field_names = set((local_field.name for local_field in self.model._meta.local_fields)) - for key in lookup_params_keys: - if key not in model_field_names: - # means k only available in typesense - value = remaining_lookup_params.pop(key) - new_lookup_params = self.model.collection_class.get_django_lookup(key, value) - remaining_lookup_params.update(new_lookup_params) - - try: - # Finally, we apply the remaining lookup parameters from the query - # string (i.e. those that haven't already been processed by the - # filters). - qs = qs.filter(**remaining_lookup_params) - except (SuspiciousOperation, ImproperlyConfigured): - # Allow certain types of errors to be re-raised as-is so that the - # caller can treat them in a special way. - raise - except Exception as e: - # Every other error is caught with a naked except, because we don't - # have any other way of validating lookup parameters. They might be - # invalid if the keyword arguments are incorrect, or if the values - # are not in the correct type, so we might get FieldError, - # ValueError, ValidationError, or ?. - raise IncorrectLookupParameters(e) + for param, value in remaining_lookup_params.items(): + try: + # Finally, we apply the remaining lookup parameters from the query + # string (i.e. those that haven't already been processed by the + # filters). + qs = qs.filter(**{param: value}) + except (SuspiciousOperation, ImproperlyConfigured): + # Allow certain types of errors to be re-raised as-is so that the + # caller can treat them in a special way. + raise + except Exception as e: + # Every other error is caught with a naked except, because we don't + # have any other way of validating lookup parameters. They might be + # invalid if the keyword arguments are incorrect, or if the values + # are not in the correct type, so we might get FieldError, + # ValueError, ValidationError, or ?. + + # for django-typesense, possibly means k only available in typesense + new_lookup_params = self.model.collection_class.get_django_lookup(param, value, e) + qs = qs.filter(**new_lookup_params) # Apply search results qs, search_may_have_duplicates = self.model_admin.get_search_results( diff --git a/django_typesense/collections.py b/django_typesense/collections.py index 2bb2544..4f9158f 100644 --- a/django_typesense/collections.py +++ b/django_typesense/collections.py @@ -198,21 +198,25 @@ def get_field(cls, name) -> TypesenseField: return fields[name] @classmethod - def get_django_lookup(cls, field, value) -> dict: + def get_django_lookup(cls, field, value, exception: Exception) -> dict: """ Get the lookup that would have been used for this field in django. Expects to find a method on the collection called `get_FIELD_lookup` otherwise a NotImplementedError is raised Args: - collection_field_name: the name of the field in the collection + field: the name of the field in the collection value: the value to look for + exception: the django exception that led us here Returns: A dictionary of the fields to the value. """ if "get_%s_lookup" % field not in cls.__dict__: - raise NotImplementedError + raise Exception([ + exception, + NotImplementedError("get_%s_lookup is not implemented" % field) + ]) method = methodcaller("get_%s_lookup" % field, value) return method(cls)