|
17 | 17 | #
|
18 | 18 | #########################################################################
|
19 | 19 | from geonode.base.enumerations import LAYER_TYPES
|
20 |
| -import re |
21 | 20 | import logging
|
22 | 21 |
|
23 | 22 | from django.db.models import Q
|
|
29 | 28 | from tastypie.constants import ALL, ALL_WITH_RELATIONS
|
30 | 29 | from tastypie.resources import ModelResource
|
31 | 30 | from tastypie import fields
|
32 |
| -from tastypie.utils import trailing_slash |
33 | 31 |
|
34 |
| -from guardian.shortcuts import get_objects_for_user |
35 |
| - |
36 |
| -from django.conf.urls import url |
37 |
| -from django.core.paginator import Paginator, InvalidPage |
38 |
| -from django.http import Http404 |
39 | 32 | from django.core.exceptions import ObjectDoesNotExist
|
40 | 33 | from django.forms.models import model_to_dict
|
41 | 34 |
|
|
67 | 60 | from .paginator import CrossSiteXHRPaginator
|
68 | 61 | from django.utils.translation import gettext as _
|
69 | 62 |
|
70 |
| -if settings.HAYSTACK_SEARCH: |
71 |
| - from haystack.query import SearchQuerySet # noqa |
72 |
| - |
73 | 63 | logger = logging.getLogger(__name__)
|
74 | 64 |
|
75 | 65 |
|
@@ -246,242 +236,6 @@ def filter_h_keywords(self, queryset, keywords):
|
246 | 236 | filtered = queryset
|
247 | 237 | return filtered
|
248 | 238 |
|
249 |
| - def build_haystack_filters(self, parameters): |
250 |
| - from haystack.inputs import Raw |
251 |
| - from haystack.query import SearchQuerySet, SQ # noqa |
252 |
| - |
253 |
| - sqs = None |
254 |
| - |
255 |
| - # Retrieve Query Params |
256 |
| - |
257 |
| - # Text search |
258 |
| - query = parameters.get("q", None) |
259 |
| - |
260 |
| - # Types and subtypes to filter (map, layer, vector, etc) |
261 |
| - type_facets = parameters.getlist("type__in", []) |
262 |
| - |
263 |
| - # If coming from explore page, add type filter from resource_name |
264 |
| - resource_filter = self._meta.resource_name.rstrip("s") |
265 |
| - if resource_filter != "base" and resource_filter not in type_facets: |
266 |
| - type_facets.append(resource_filter) |
267 |
| - |
268 |
| - # Publication date range (start,end) |
269 |
| - date_end = parameters.get("date__lte", None) |
270 |
| - date_start = parameters.get("date__gte", None) |
271 |
| - |
272 |
| - # Topic category filter |
273 |
| - category = parameters.getlist("category__identifier__in") |
274 |
| - |
275 |
| - # Keyword filter |
276 |
| - keywords = parameters.getlist("keywords__slug__in") |
277 |
| - |
278 |
| - # Region filter |
279 |
| - regions = parameters.getlist("regions__name__in") |
280 |
| - |
281 |
| - # Owner filters |
282 |
| - owner = parameters.getlist("owner__username__in") |
283 |
| - |
284 |
| - # Sort order |
285 |
| - sort = parameters.get("order_by", "relevance") |
286 |
| - |
287 |
| - # Geospatial Elements |
288 |
| - bbox = parameters.get("extent", None) |
289 |
| - |
290 |
| - # Filter by Type and subtype |
291 |
| - if type_facets is not None: |
292 |
| - types = [] |
293 |
| - subtypes = [] |
294 |
| - |
295 |
| - for type in type_facets: |
296 |
| - if type in {"map", "layer", "document", "user"}: |
297 |
| - # Type is one of our Major Types (not a sub type) |
298 |
| - types.append(type) |
299 |
| - elif type in LAYER_TYPES: |
300 |
| - subtypes.append(type) |
301 |
| - |
302 |
| - if "vector" in subtypes and "vector_time" not in subtypes: |
303 |
| - subtypes.append("vector_time") |
304 |
| - |
305 |
| - if len(subtypes) > 0: |
306 |
| - types.append("layer") |
307 |
| - sqs = SearchQuerySet().narrow(f"subtype:{','.join(map(str, subtypes))}") |
308 |
| - |
309 |
| - if len(types) > 0: |
310 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).narrow(f"type:{','.join(map(str, types))}") |
311 |
| - |
312 |
| - # Filter by Query Params |
313 |
| - # haystack bug? if boosted fields aren't included in the |
314 |
| - # query, then the score won't be affected by the boost |
315 |
| - if query: |
316 |
| - if query.startswith('"') or query.startswith("'"): |
317 |
| - # Match exact phrase |
318 |
| - phrase = query.replace('"', "") |
319 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter( |
320 |
| - SQ(title__exact=phrase) | SQ(description__exact=phrase) | SQ(content__exact=phrase) |
321 |
| - ) |
322 |
| - else: |
323 |
| - words = [w for w in re.split(r"\W", query, flags=re.UNICODE) if w] |
324 |
| - for i, search_word in enumerate(words): |
325 |
| - if i == 0: |
326 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter( |
327 |
| - SQ(title=Raw(search_word)) | SQ(description=Raw(search_word)) | SQ(content=Raw(search_word)) |
328 |
| - ) |
329 |
| - elif search_word in {"AND", "OR"}: |
330 |
| - pass |
331 |
| - elif words[i - 1] == "OR": # previous word OR this word |
332 |
| - sqs = sqs.filter_or( |
333 |
| - SQ(title=Raw(search_word)) | SQ(description=Raw(search_word)) | SQ(content=Raw(search_word)) |
334 |
| - ) |
335 |
| - else: # previous word AND this word |
336 |
| - sqs = sqs.filter( |
337 |
| - SQ(title=Raw(search_word)) | SQ(description=Raw(search_word)) | SQ(content=Raw(search_word)) |
338 |
| - ) |
339 |
| - |
340 |
| - # filter by category |
341 |
| - if category: |
342 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).narrow(f"category:{','.join(map(str, category))}") |
343 |
| - |
344 |
| - # filter by keyword: use filter_or with keywords_exact |
345 |
| - # not using exact leads to fuzzy matching and too many results |
346 |
| - # using narrow with exact leads to zero results if multiple keywords |
347 |
| - # selected |
348 |
| - if keywords: |
349 |
| - for keyword in keywords: |
350 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter_or(keywords_exact=keyword) |
351 |
| - |
352 |
| - # filter by regions: use filter_or with regions_exact |
353 |
| - # not using exact leads to fuzzy matching and too many results |
354 |
| - # using narrow with exact leads to zero results if multiple keywords |
355 |
| - # selected |
356 |
| - if regions: |
357 |
| - for region in regions: |
358 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter_or(regions_exact__exact=region) |
359 |
| - |
360 |
| - # filter by owner |
361 |
| - if owner: |
362 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).narrow(f"owner__username:{','.join(map(str, owner))}") |
363 |
| - |
364 |
| - # filter by date |
365 |
| - if date_start: |
366 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter(SQ(date__gte=date_start)) |
367 |
| - |
368 |
| - if date_end: |
369 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).filter(SQ(date__lte=date_end)) |
370 |
| - |
371 |
| - # Filter by geographic bounding box |
372 |
| - if bbox: |
373 |
| - left, bottom, right, top = bbox.split(",") |
374 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).exclude( |
375 |
| - SQ(bbox_top__lte=bottom) |
376 |
| - | SQ(bbox_bottom__gte=top) |
377 |
| - | SQ(bbox_left__gte=right) |
378 |
| - | SQ(bbox_right__lte=left) |
379 |
| - ) |
380 |
| - |
381 |
| - # Apply sort |
382 |
| - if sort.lower() == "-date": |
383 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("-date") |
384 |
| - elif sort.lower() == "date": |
385 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("date") |
386 |
| - elif sort.lower() == "title": |
387 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("title_sortable") |
388 |
| - elif sort.lower() == "-title": |
389 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("-title_sortable") |
390 |
| - elif sort.lower() == "-popular_count": |
391 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("-popular_count") |
392 |
| - else: |
393 |
| - sqs = (SearchQuerySet() if sqs is None else sqs).order_by("-date") |
394 |
| - |
395 |
| - return sqs |
396 |
| - |
397 |
| - def get_search(self, request, **kwargs): |
398 |
| - self.method_check(request, allowed=["get"]) |
399 |
| - self.is_authenticated(request) |
400 |
| - self.throttle_check(request) |
401 |
| - |
402 |
| - # Get the list of objects that matches the filter |
403 |
| - sqs = self.build_haystack_filters(request.GET) |
404 |
| - |
405 |
| - if not settings.SKIP_PERMS_FILTER: |
406 |
| - filter_set = get_objects_for_user(request.user, "base.view_resourcebase") |
407 |
| - |
408 |
| - filter_set = get_visible_resources( |
409 |
| - filter_set, |
410 |
| - request.user if request else None, |
411 |
| - admin_approval_required=settings.ADMIN_MODERATE_UPLOADS, |
412 |
| - unpublished_not_visible=settings.RESOURCE_PUBLISHING, |
413 |
| - private_groups_not_visibile=settings.GROUP_PRIVATE_RESOURCES, |
414 |
| - ) |
415 |
| - |
416 |
| - filter_set_ids = filter_set.values_list("id") |
417 |
| - # Do the query using the filterset and the query term. Facet the |
418 |
| - # results |
419 |
| - if len(filter_set) > 0: |
420 |
| - sqs = ( |
421 |
| - sqs.filter(id__in=filter_set_ids) |
422 |
| - .facet("type") |
423 |
| - .facet("subtype") |
424 |
| - .facet("owner") |
425 |
| - .facet("keywords") |
426 |
| - .facet("regions") |
427 |
| - .facet("category") |
428 |
| - ) |
429 |
| - else: |
430 |
| - sqs = None |
431 |
| - else: |
432 |
| - sqs = sqs.facet("type").facet("subtype").facet("owner").facet("keywords").facet("regions").facet("category") |
433 |
| - |
434 |
| - if sqs: |
435 |
| - # Build the Facet dict |
436 |
| - facets = {} |
437 |
| - for facet in sqs.facet_counts()["fields"]: |
438 |
| - facets[facet] = {} |
439 |
| - for item in sqs.facet_counts()["fields"][facet]: |
440 |
| - facets[facet][item[0]] = item[1] |
441 |
| - |
442 |
| - # Paginate the results |
443 |
| - paginator = Paginator(sqs, request.GET.get("limit")) |
444 |
| - |
445 |
| - try: |
446 |
| - page = paginator.page(int(request.GET.get("offset") or 0) / int(request.GET.get("limit") or 0 + 1)) |
447 |
| - except InvalidPage: |
448 |
| - raise Http404("Sorry, no results on that page.") |
449 |
| - |
450 |
| - if page.has_previous(): |
451 |
| - previous_page = page.previous_page_number() |
452 |
| - else: |
453 |
| - previous_page = 1 |
454 |
| - if page.has_next(): |
455 |
| - next_page = page.next_page_number() |
456 |
| - else: |
457 |
| - next_page = 1 |
458 |
| - total_count = sqs.count() |
459 |
| - objects = page.object_list |
460 |
| - else: |
461 |
| - next_page = 0 |
462 |
| - previous_page = 0 |
463 |
| - total_count = 0 |
464 |
| - facets = {} |
465 |
| - objects = [] |
466 |
| - |
467 |
| - object_list = { |
468 |
| - "meta": { |
469 |
| - "limit": settings.CLIENT_RESULTS_LIMIT, |
470 |
| - "next": next_page, |
471 |
| - "offset": int(getattr(request.GET, "offset", 0)), |
472 |
| - "previous": previous_page, |
473 |
| - "total_count": total_count, |
474 |
| - "facets": facets, |
475 |
| - }, |
476 |
| - "objects": [self.get_haystack_api_fields(x) for x in objects], |
477 |
| - } |
478 |
| - |
479 |
| - self.log_throttled_access(request) |
480 |
| - return self.create_response(request, object_list) |
481 |
| - |
482 |
| - def get_haystack_api_fields(self, haystack_object): |
483 |
| - return {k: v for k, v in haystack_object.get_stored_fields().items() if not re.search("_exact$|_sortable$", k)} |
484 |
| - |
485 | 239 | def get_list(self, request, **kwargs):
|
486 | 240 | """
|
487 | 241 | Returns a serialized list of resources.
|
@@ -574,16 +328,7 @@ def create_response(self, request, data, response_class=HttpResponse, response_o
|
574 | 328 | return response_class(content=serialized, content_type=build_content_type(desired_format), **response_kwargs)
|
575 | 329 |
|
576 | 330 | def prepend_urls(self):
|
577 |
| - if settings.HAYSTACK_SEARCH: |
578 |
| - return [ |
579 |
| - url( |
580 |
| - r"^(?P<resource_name>{})/search{}$".format(self._meta.resource_name, trailing_slash()), |
581 |
| - self.wrap_view("get_search"), |
582 |
| - name="api_get_search", |
583 |
| - ), |
584 |
| - ] |
585 |
| - else: |
586 |
| - return [] |
| 331 | + return [] |
587 | 332 |
|
588 | 333 | def hydrate_title(self, bundle):
|
589 | 334 | title = bundle.data.get("title", None)
|
|
0 commit comments