在Django中进行简单搜索

Oli*_*Oli 25 django search

我有一个非常简单的博客应用程序,我想为它添加一个非常简单的搜索功能.

我的模型有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
Run Code Online (Sandbox Code Playgroud)

我不需要谷歌.我不想搜索评论(无论如何都在Disqus上搜索).我只想要一个日期排名,关键字过滤的帖子集.

我在谷歌上找到的某种形式的"django"和"搜索"的东西都带来了非常复杂的Haystack +后端解决方案.我不需要那一切.我不想在低使用率功能上占用更多资源(在我移植到Django之前我曾经有一个搜索框,而且它每个月可能有4次搜索).

我花时间在这里问(而不是只是写一个凌乱的小脚本)的原因是这已经存在于管理员.您可以设置要搜索的列,然后只搜索它"只是工作".

有没有办法处理管理员提供的搜索并将其拉入我面向用户的应用程序?

Lud*_*mer 45

如果你想要一个非常简单的搜索,你可以使用icontains查找和Q对象:

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))
Run Code Online (Sandbox Code Playgroud)

你还应该注意到,干草堆不一定要"非常复杂".您可以在不到15分钟的时间内使用Whoosh后端设置haystack.

2016更新:在版本1.10中,Django添加了全文搜索支持(仅限PostgreSQL).使用新模块的原始问题的答案可能如下所示:

from django.contrib.postgres.search import SearchVector

results = BlogPost.objects.annotate(
    search=SearchVector('title', 'intro', 'content'),
).filter(search=your_search_query)
Run Code Online (Sandbox Code Playgroud)

新的全文搜索模块包含更多功能(例如按相关性排序),您可以在文档中阅读它们.


Lak*_*sad 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
Run Code Online (Sandbox Code Playgroud)

显然,它使用数据库选项来执行搜索.如果没有别的,你应该能够重用它的一些代码.

所以文档也说:http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

但是,全文搜索使用mysql索引(仅当您使用mysql时).