Django Library PyGal
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. from django.conf import settings
  2. import fstools
  3. import logging
  4. from .models import Item
  5. import os
  6. from whoosh.fields import Schema, ID, TEXT, KEYWORD, NUMERIC, DATETIME
  7. from whoosh.qparser.dateparse import DateParserPlugin
  8. from whoosh import index, qparser
  9. from pygal.models import TYPE_FOLDER
  10. try:
  11. from config import APP_NAME as ROOT_LOGGER_NAME
  12. except ImportError:
  13. ROOT_LOGGER_NAME = 'root'
  14. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  15. SCHEMA = Schema(
  16. rel_path=ID(unique=True, stored=True),
  17. # Item
  18. name=TEXT,
  19. type=TEXT,
  20. favourite_of=KEYWORD,
  21. datetime=DATETIME,
  22. size=NUMERIC,
  23. # Tag
  24. tag=KEYWORD,
  25. # Image Cache
  26. exposure_program=TEXT,
  27. exposure_time=NUMERIC,
  28. flash=TEXT,
  29. f_number=NUMERIC,
  30. focal_length=NUMERIC,
  31. lon=NUMERIC,
  32. lat=NUMERIC,
  33. height=NUMERIC,
  34. iso=NUMERIC,
  35. camera=TEXT,
  36. orientation=NUMERIC,
  37. width=NUMERIC,
  38. # Audio Cache
  39. album=TEXT,
  40. artist=TEXT,
  41. bitrate=NUMERIC,
  42. duration=NUMERIC,
  43. genre=TEXT,
  44. title=TEXT,
  45. track=NUMERIC,
  46. year=NUMERIC,
  47. #
  48. ratio=NUMERIC,
  49. )
  50. def create_index():
  51. logger.debug('Search Index created.')
  52. return index.create_in(settings.WHOOSH_PATH, schema=SCHEMA)
  53. def load_index():
  54. if not os.path.exists(settings.WHOOSH_PATH):
  55. fstools.mkdir(settings.WHOOSH_PATH)
  56. try:
  57. ix = index.open_dir(settings.WHOOSH_PATH)
  58. except index.EmptyIndexError:
  59. ix = create_index()
  60. else:
  61. logger.debug('Search Index opened.')
  62. return ix
  63. def item_is_supported(item):
  64. return item.type != TYPE_FOLDER
  65. def add_item(ix, item):
  66. # Collect data for the item
  67. #
  68. data = {
  69. 'rel_path': item.rel_path,
  70. 'name': os.path.splitext(item.rel_path.split('/')[-1])[0],
  71. 'type': item.type,
  72. }
  73. favourite_of = item.favourite_of.all()
  74. if len(favourite_of) > 0:
  75. data['favourite_of'] = ' '.join([u.username for u in favourite_of])
  76. tags = item.tag_set.all()
  77. if len(tags) > 0:
  78. data['tag'] = ' '.join([t.text for t in tags])
  79. for key, value in item.cached_item_data.items():
  80. data[key] = value
  81. # Write data to the index
  82. #
  83. with ix.writer() as w:
  84. logger.info('Adding document with rel_path=%s to the search index.', data.get('rel_path'))
  85. w.add_document(**data)
  86. for key in data:
  87. logger.debug(' - Adding %s=%s', key, repr(data[key]))
  88. def delete_item(ix, item):
  89. with ix.writer() as w:
  90. logger.info('Removing document with rel_path=%s from the search index.', item.rel_path)
  91. w.delete_by_term("rel_path", item.rel_path)
  92. def update_item(ix, item):
  93. if item_is_supported(item):
  94. delete_item(ix, item)
  95. add_item(ix, item)
  96. def rebuild_index(ix):
  97. for item in Item.objects.all().exclude(type=TYPE_FOLDER):
  98. add_item(ix, item)
  99. return len(Item.objects.all().exclude(type=TYPE_FOLDER))
  100. def search(ix, search_txt):
  101. qp = qparser.MultifieldParser(['name', 'tag'], ix.schema)
  102. qp.add_plugin(DateParserPlugin(free=True))
  103. q = qp.parse(search_txt)
  104. with ix.searcher() as s:
  105. results = s.search(q, limit=None)
  106. rpl = []
  107. for hit in results:
  108. rpl.append(hit['rel_path'])
  109. return Item.objects.filter(rel_path__in=rpl)