diff --git a/search/search.py b/search/search.py index 17dc9a0..a2558e5 100644 --- a/search/search.py +++ b/search/search.py @@ -46,6 +46,26 @@ def trigram_search(query: str, queryset, fields: List[str]): return queryset.annotate(similarity=trigram_query).order_by('-similarity') +def get_field_type(model, field): + """ + Determine a type name of Django field. + + @todo #stb-537:30m Create a class instead this function. + See there for details: https://github.com/fidals/refarm-site/pull/315/files#r270500698 + + """ + if '__' in field: + # translate `product__name` to `name` and swap `model` to `Product` + model_name, field = field.split('__') + model = model._meta.get_field(model_name).related_model + + return ( + model._meta + .get_field(field) + .get_internal_type() + ) + + class Search: def __init__( self, name, qs, fields, @@ -59,8 +79,8 @@ def __init__( :param fields: list of query lookups :param template_fields: list fields for django templates :param min_similarity: used to trigram similarity search - :param redirect_field: when client search for this field, the result is - redirected to custom page + :param redirect_field: when client search for this field, the result is + redirected to custom page """ self.name = name self.fields = fields @@ -73,12 +93,8 @@ def __init__( self.decimal_fields = [] for field in fields: - field_type = ( - self.qs.model._meta - .get_field(field.partition('__')[0]) - .get_internal_type() - ) - if field_type in ['CharField', 'TextField']: + type_ = get_field_type(self.qs.model, field) + if type_ in ['CharField', 'TextField']: # Trigram similarity supports only these two entity types self.trigram_fields.append(field) else: @@ -86,9 +102,7 @@ def __init__( def search(self, term: str): def _trigram_search(query): - """ - Just a shortcut for trigram_search function call - """ + """Just a shortcut for trigram_search function call.""" return trigram_search(query, self.qs, self.trigram_fields).filter( similarity__gt=self.min_similarity )