1、在 SearchForm 类的 search() 中:
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
return self.no_query_found()
sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])
if self.load_all:
sqs = sqs.load_all()
return sqs
ps: 1、self.searchqueryset 拿到了所有做搜索的 model 结果
2、self.cleaned_data['q'] 是搜索的内容
3、sqs 是与 搜索内容 匹配的结果(全部表的数据)
2、在自定义的搜索结果视图类中
class OrderSearchView(SearchView):
def __init__(self):
super(OrderSearchView, self).__init__(template='searches/search_order.html',
load_all=True,
form_class=ModelSearchFormCustom,
searchqueryset=SearchQuerySetCustom(),
results_per_page=None)
if not isinstance(self.searchqueryset, SearchQuerySetCustom):
self.searchqueryset = SearchQuerySetCustom()
self.searchqueryset._models = (Order,)
def get_results(self):
kwargs = {
'username': self.request.user.username
}
return self.form.search(**kwargs).order_by('-create_time')
ps: 1、template 指定 结果页面
2、form_class 指定 自定义 继承ModelSearchForm的类, ModelSearchForm继承自SearchForm
3、searchqueryset 指定 自定义 继承SearchQuerySet(实现了诸如filter的函数、查询与搜索内容相符的结果)的类
4、self.searchqueryset._models 指定希望搜索结果是 某一个model的结果
5、(重要)kwargs 里的 username 必须是 OrderIndex 里定义了的, 也就是说对搜索结果排序、过滤(filtr)等操作的的字段不能用原Order表的字段
3、OrderSearchView 所对应的 Index 类
from haystack import indexes
class OrderIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
data_id = indexes.IntegerField(model_attr='id', stored=False)
username = indexes.CharField(model_attr='user__username')
create_time = indexes.DateTimeField(model_attr='create_time')
def get_model(self):
return Order
def index_queryset(self, using=None):
return self.get_model().objects.all()
ps: 1、username、create_time 是自己增加的过滤条件,username指定了与Order表关联的User表的username字段
2、要用ID排序的话,必须加 stored=False,不保存到索引中去。因为haystack索引主键是ID,如果保存到索引中,排序的时候会报返回两个ID
4、以下是自定义的两个类
from haystack.forms import ModelSearchForm
from haystack.query import SearchQuerySet
from haystack.inputs import AutoQuery, Raw
from haystack.backends import SQ
class SearchQuerySetCustom(SearchQuerySet):
def __init__(self, using=None, query=None):
super(SearchQuerySetCustom, self).__init__(using, query)
self._models = ()
def auto_query(self, **kwargs):
"""
Performs a best guess constructing the search query.
This method is somewhat naive but works well enough for the simple,
common cases.
"""
return self.filter(**kwargs)
def exclude(self, *args, **kwargs):
"""Narrows the search by ensuring certain attributes are not included."""
clone = self.models(*self._models)
clone.query.add_filter(~SQ(*args, **kwargs))
return clone
def filter_and(self, *args, **kwargs):
"""Narrows the search by looking for (and including) certain attributes."""
clone = self.models(*self._models)
clone.query.add_filter(SQ(*args, **kwargs))
return clone
def filter_or(self, *args, **kwargs):
"""Narrows the search by ensuring certain attributes are not included."""
clone = self.models(*self._models)
clone.query.add_filter(SQ(*args, **kwargs), use_or=True)
return clone
class ModelSearchFormCustom(ModelSearchForm):
def search(self, fieldname='content', **kwargs):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
return self.no_query_found()
kwargs[fieldname] = AutoQuery(self.cleaned_data['q'])
sqs = self.searchqueryset.auto_query(**kwargs)
if self.load_all:
sqs = sqs.load_all()
return sqs.models(*self.get_models())
# return sqs
ps: 1、OrderSearchView 类里 self.form是 ModelSearchFormCustom对象,所以self.form.search(**kwargs)调用的方法就是 ModelSearchFormCustom 里的search方法
2、原 ModelSearchForm 的search方法:
def search(self):
sqs = super(ModelSearchForm, self).search()
return sqs.models(*self.get_models())
此方法里的search方法(SearchForm类):
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
return self.no_query_found()
sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])
if self.load_all:
sqs = sqs.load_all()
return sqs
3、默认使用的方法是 filter_and()
ps: 1、 没有大量测试,但是目前来看没什么问题
2、不知道这个搜索框架底层到底是什么实现的,也就是说先筛选指定model,再做过滤会不会更快
附上本地测试结果:服务器、数据库(mysql)在新加坡:
3、linux 命令重建索引 免输入 “y”:echo "y"|python3 /root/项目/manage.py rebuild_index
4、linux 一行输入两个命令:Linux: mkdir -p /root/abc && cp * -rf "$_"(命令大意是:强制复制 当前目录下的所有 到 mkdir创建的 “abc” 目录下)
二、升级优化:
1、假如有以下几张表