search.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
  2. from django.utils.translation import ugettext_lazy as _
  3. from misago.conf import settings
  4. from misago.core.shortcuts import paginate, pagination_dict
  5. from misago.search import SearchProvider
  6. from .filtersearch import filter_search
  7. from .models import Post, Thread
  8. from .permissions import exclude_invisible_threads
  9. from .serializers import FeedSerializer
  10. from .utils import add_categories_to_items
  11. from .viewmodels import ThreadsRootCategory
  12. class SearchThreads(SearchProvider):
  13. name = _("Threads")
  14. icon = 'forum'
  15. url = 'threads'
  16. def search(self, query, page=1):
  17. root_category = ThreadsRootCategory(self.request)
  18. threads_categories = [root_category.unwrap()] + root_category.subcategories
  19. if len(query) > 2:
  20. visible_threads = exclude_invisible_threads(
  21. self.request.user, threads_categories, Thread.objects
  22. )
  23. results = search_threads(self.request, query, visible_threads)
  24. else:
  25. results = []
  26. list_page = paginate(
  27. results,
  28. page,
  29. settings.MISAGO_POSTS_PER_PAGE,
  30. settings.MISAGO_POSTS_TAIL,
  31. allow_explicit_first_page=True,
  32. )
  33. paginator = pagination_dict(list_page)
  34. posts = list(list_page.object_list)
  35. threads = []
  36. for post in posts:
  37. threads.append(post.thread)
  38. add_categories_to_items(root_category.unwrap(), threads_categories, posts + threads)
  39. results = {
  40. 'results': FeedSerializer(posts, many=True, context={
  41. 'user': self.request.user,
  42. }).data,
  43. }
  44. results.update(paginator)
  45. return results
  46. def search_threads(request, query, visible_threads):
  47. search_query = SearchQuery(
  48. filter_search(query),
  49. config=settings.MISAGO_SEARCH_CONFIG,
  50. )
  51. search_vector = SearchVector(
  52. 'search_document',
  53. config=settings.MISAGO_SEARCH_CONFIG,
  54. )
  55. return Post.objects.select_related('thread', 'poster', 'poster__rank').filter(
  56. is_event=False,
  57. is_hidden=False,
  58. is_unapproved=False,
  59. thread_id__in=visible_threads.values('id'),
  60. search_vector=search_query,
  61. ).annotate(rank=SearchRank(search_vector, search_query)).order_by('-rank', '-id')