我有一个非常简单的博客应用程序,我想为它添加一个非常简单的搜索功能。
我的模型有3个关键字段。
class BlogPost(models.Model):
title = models.CharField(max_length=100) # the title
intro = models.TextField(blank=True, null=True) # an extract
content = models.TextField(blank=True, null=True) # full post
我不需要谷歌。我不想搜索评论(无论如何都在Disqus上搜索)。我只想要一个日期排名,关键字过滤的帖子集。
我在谷歌上找到的某种形式的“django”和“搜索”的东西都带来了非常复杂的Haystack +后端解决方案。我不需要所有这些。我不想在使用率低的功能上占用更多资源(在我移植到Django之前我曾经有一个搜索框,而且它每个月可能有4次搜索)。
我需要时间在这里问一下(而不仅仅是写一个凌乱的小脚本)的原因是这已经存在于管理员中。您可以设置要搜索的列,然后只搜索它,“只是工作”。
有没有办法处理管理员提供的搜索并将其拉入面向用户的应用程序?
答案 0 :(得分:44)
如果您想要一个非常简单的搜索,可以使用icontains
查询和Q
object:
from django.db.models import Q
results = BlogPost.objects.filter(Q(title__icontains=your_search_query) | Q(intro__icontains=your_search_query) | Q(content__icontains=your_search_query))
你还应该注意到,干草堆不一定要“非常复杂”。您可以在不到15分钟的时间内使用Whoosh后端设置干草堆。
更新2016:在版本1.10中,Django添加了a full text search support(仅限PostgreSQL)。使用新模块的原始问题的答案可能如下所示:
from django.contrib.postgres.search import SearchVector
results = BlogPost.objects.annotate(
search=SearchVector('title', 'intro', 'content'),
).filter(search=your_search_query)
新的全文搜索模块包含更多功能(例如按相关性排序),您可以read about them in the documentation。
答案 1 :(得分:5)
来自django来源:http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/main.py
# Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
if self.search_fields and self.query:
for bit in self.query.split():
or_queries = [models.Q(**{construct_search(str(field_name)): bit}) for field_name in self.search_fields]
qs = qs.filter(reduce(operator.or_, or_queries))
for field_name in self.search_fields:
if '__' in field_name:
qs = qs.distinct()
break
显然,它使用数据库选项来执行搜索。如果不出意外,您应该能够重用其中的一些代码。
然而,全文搜索使用mysql索引(仅当您使用mysql时)。
答案 2 :(得分:3)
您将使用__search运算符。它记录在Django QuerySet API Reference中。还有istartswith,它使用搜索进行不区分大小写的开始。
这是一个工作示例(改编自我自己的Django网站):
def search(request):
try:
q = request.GET['q']
posts = BlogPost.objects.filter(title__search=q) | \
BlogPost.objects.filter(intro__search=q) | \
BlogPost.objects.filter(content__search=q)
return render_to_response('search/results.html', {'posts':posts, 'q':q})
except KeyError:
return render_to_response('search/results.html')
请注意,__ search仅在MySQL中可用,并且需要直接操作数据库以添加全文索引。有关其他详细信息,请参阅MySQL documentation。
答案 3 :(得分:2)
如果您希望它像管理员一样工作,您可以尝试我的迷你库Django simple search。它基本上是管理搜索功能的一个端口。用pip安装它:
pip install django-simple-search
并使用它:
from simple_search import search_filter
from .models import BlogPost
search_fields = ['^title', 'intro', 'content']
query = 'search term here'
posts = BlogPost.objects.filter(search_filter(search_fields, query))
我还写了一篇关于它的博文:https://gregbrown.co/projects/django-simple-search