mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-12 17:23:15 +00:00
DB search now returns a SearchResults object
Previously, it returned a QuerySet which gave the database backend much more API than the Elasticsearch backend has. Which could potentially cause issues if the developer is using the DB backend locally and the Elasticsearch backend on their production server. Fixes #460
This commit is contained in:
parent
ca17d062c3
commit
ab896e318a
1 changed files with 54 additions and 31 deletions
|
|
@ -1,6 +1,57 @@
|
|||
from django.db import models
|
||||
|
||||
from wagtail.wagtailsearch.backends.base import BaseSearch
|
||||
from wagtail.wagtailsearch.backends.base import BaseSearch, BaseSearchResults
|
||||
|
||||
|
||||
class DBSearchQuery(object):
|
||||
def __init__(self, queryset, query_string, fields=None):
|
||||
self.queryset = queryset
|
||||
self.query_string = query_string
|
||||
self.fields = fields
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset
|
||||
model = queryset.model
|
||||
|
||||
if self.query_string is not None:
|
||||
# Get fields
|
||||
fields = self.fields or [field.field_name for field in model.get_searchable_search_fields()]
|
||||
|
||||
# Get terms
|
||||
terms = self.query_string.split()
|
||||
if not terms:
|
||||
return model.objects.none()
|
||||
|
||||
# Filter by terms
|
||||
for term in terms:
|
||||
term_query = models.Q()
|
||||
for field_name in fields:
|
||||
# Check if the field exists (this will filter out indexed callables)
|
||||
try:
|
||||
model._meta.get_field_by_name(field_name)
|
||||
except:
|
||||
continue
|
||||
|
||||
# Filter on this field
|
||||
term_query |= models.Q(**{'%s__icontains' % field_name: term})
|
||||
|
||||
queryset = queryset.filter(term_query)
|
||||
|
||||
# Distinct
|
||||
queryset = queryset.distinct()
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
class DBSearchResults(BaseSearchResults):
|
||||
def get_queryset(self):
|
||||
return self.query.get_queryset()[self.start:self.stop]
|
||||
|
||||
def _do_search(self):
|
||||
return self.get_queryset()
|
||||
|
||||
def _do_count(self):
|
||||
return self.get_queryset().count()
|
||||
|
||||
|
||||
class DBSearch(BaseSearch):
|
||||
|
|
@ -20,38 +71,10 @@ class DBSearch(BaseSearch):
|
|||
pass # Not needed
|
||||
|
||||
def add_bulk(self, model, obj_list):
|
||||
pass # Not needed
|
||||
return # Not needed
|
||||
|
||||
def delete(self, obj):
|
||||
pass # Not needed
|
||||
|
||||
def _search(self, queryset, query_string, fields=None):
|
||||
if query_string is not None:
|
||||
# Get fields
|
||||
if fields is None:
|
||||
fields = [field.field_name for field in queryset.model.get_searchable_search_fields()]
|
||||
|
||||
# Get terms
|
||||
terms = query_string.split()
|
||||
if not terms:
|
||||
return queryset.model.objects.none()
|
||||
|
||||
# Filter by terms
|
||||
for term in terms:
|
||||
term_query = models.Q()
|
||||
for field_name in fields:
|
||||
# Check if the field exists (this will filter out indexed callables)
|
||||
try:
|
||||
queryset.model._meta.get_field_by_name(field_name)
|
||||
except:
|
||||
continue
|
||||
|
||||
# Filter on this field
|
||||
term_query |= models.Q(**{'%s__icontains' % field_name: term})
|
||||
|
||||
queryset = queryset.filter(term_query)
|
||||
|
||||
# Distinct
|
||||
queryset = queryset.distinct()
|
||||
|
||||
return queryset
|
||||
return DBSearchResults(self, DBSearchQuery(queryset, query_string, fields=fields))
|
||||
|
|
|
|||
Loading…
Reference in a new issue