__init__.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. from django.utils.translation import ugettext_lazy as _
  2. class SearchException(Exception):
  3. def __init__(self, message):
  4. self.message = message
  5. class SearchQuery(object):
  6. def __init__(self, raw_query=None):
  7. """
  8. Build search query object
  9. """
  10. if raw_query:
  11. self.parse_query(raw_query)
  12. def parse_query(self, raw_query):
  13. """
  14. Parse raw search query into dict of lists of words that should be found and cant be found in string
  15. """
  16. self.criteria = {'+': [], '-': []}
  17. for word in unicode(raw_query).split():
  18. # Trim word and skip it if its empty
  19. word = unicode(word).strip().lower()
  20. if len(word) == 0:
  21. pass
  22. # Find word mode
  23. mode = '+'
  24. if word[0] == '-':
  25. mode = '-'
  26. word = unicode(word[1:]).strip()
  27. # Strip extra crap
  28. word = ''.join(e for e in word if e.isalnum())
  29. # Slice word?
  30. if len(word) <= 3:
  31. raise SearchException(_("One or more search phrases are shorter than four characters."))
  32. if mode == '+':
  33. if len(word) == 5:
  34. word = word[0:-1]
  35. if len(word) == 6:
  36. word = word[0:-2]
  37. if len(word) > 6:
  38. word = word[0:-3]
  39. self.criteria[mode].append(word)
  40. # Complain that there are no positive matches
  41. if not self.criteria['+'] and not self.criteria['-']:
  42. raise SearchException(_("Search query is invalid."))
  43. def search(self, value):
  44. """
  45. See if value meets search criteria, return True for success and False otherwhise
  46. """
  47. try:
  48. value = unicode(value).strip().lower()
  49. # Search for only
  50. if self.criteria['+'] and not self.criteria['-']:
  51. return self.search_for(value)
  52. # Search against only
  53. if self.criteria['-'] and not self.criteria['+']:
  54. return self.search_against(value)
  55. # Search if contains for values but not against values
  56. return self.search_for(value) and not self.search_against(value)
  57. except AttributeError:
  58. raise SearchException(_("You have to define search query before you will be able to search."))
  59. def search_for(self, value):
  60. """
  61. See if value is required
  62. """
  63. for word in self.criteria['+']:
  64. if value.find(word) != -1:
  65. return True
  66. return False
  67. def search_against(self, value):
  68. """
  69. See if value is forbidden
  70. """
  71. for word in self.criteria['-']:
  72. if value.find(word) != -1:
  73. return True
  74. return False