text: EQUAL = 0
  CONTAINS = 1
  STARTS_WITH = 2
  ENDS_WITH = 3
  
  
  def filter_queryset(queryset, attr, search, *, case_sensitive=False):
      mode = get_mode(search)
      search = search.strip("*")
  
      if not search:
          return queryset
  
      queryset_filter = get_queryset_filter(
          attr, mode, search, case_sensitive=case_sensitive
      )
      return queryset.filter(**queryset_filter)
  
  
  def get_mode(search):
      if search.startswith("*") and search.endswith("*"):
          return CONTAINS
      if search.endswith("*"):
          return STARTS_WITH
      if search.startswith("*"):
          return ENDS_WITH
      return EQUAL
  
  
  def get_queryset_filter(attr, mode, search, *, case_sensitive=False):
      if mode is STARTS_WITH:
          if case_sensitive:
              return {"%s__startswith" % attr: search}
          return {"%s__istartswith" % attr: search}
  
      if mode is ENDS_WITH:
          if case_sensitive:
              return {"%s__endswith" % attr: search}
          return {"%s__iendswith" % attr: search}
  
      if mode is CONTAINS:
          if case_sensitive:
              return {"%s__contains" % attr: search}
          return {"%s__icontains" % attr: search}
  
      if case_sensitive:
          return {attr: search}
  
      return {"%s__iexact" % attr: search}
  