在django搜索结果页面上突出显示搜索字词

时间:2017-09-24 00:44:11

标签: django postgresql django-rest-framework full-text-search

如何使用PostgreSQL full text search在Django 1.11中创建搜索结果页面,其中搜索的术语会突出显示?

3 个答案:

答案 0 :(得分:7)

即使django不支持postgresql的ts_headline功能。您可以手动将其作为函数应用于QuerySet以进行注释。

我们需要额外的功能来使用django ORM。以下是ts_headline的示例。 [此示例函数的original_source已链接here]

标题功能样本:

from django.db import models
from django.contrib.postgres.search import Value, Func


class Headline(Func):
    function = 'ts_headline'

    def __init__(self, field, query, config=None, options=None, **extra):
        expressions = [field, query]
        if config:
            expressions.insert(0, Value(config))
        if options:
            expressions.append(Value(options))
        extra.setdefault('output_field', models.TextField())
        super().__init__(*expressions, **extra)

使用上述功能,您可以在QuerySet上使用它来注释

示例模型定义

class Video(Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=128, verbose_name="Title")

在模型标题

上获取突出显示的搜索结果的步骤
  1. 过滤并获取需要注释的QuerySet
  2. 使用标题功能进行注释
  3. 获取文档的值
  4. 过滤对象

    Video.objects.filter(filter_query)
    

    filter_query 是Q()over title filter_query = Q(title__contains = term)

    带有标题数据的注释

    Video.objects.filter(filter_query).annotate(title_highlight=Headline(F('title'), text_search_query))
    

    ts_headline 直接从文档而不是从ts_vector获取输入,因此我们必须传递有关它应该访问哪个字段的信息以及它应该在其上执行的SearchQuery。

    text_Search_query 是SearchQuery Object,其输入与filter_query相同 text_search_query = SearchQuery(term)

    现在,在注释之后,此查询集在所有名为 title_highlight 的对象中包含一个额外字段,其中包含您想要的结果:

    these <b>loans</b> not being repaired

    从注释字段中获取值

    在QuerySet上使用values_list,您可以从这些带注释的字段中获取值。

    最终代码:

    Video.objects.filter(filter_query).annotate(title_highlight=Headline(F('title'), text_search_query)).values_from('title','title_highlight')
    

答案 1 :(得分:0)

在 Django 3.1 中,现在有一个 SearchHeadline 类,它使这个任务变得更加简单。

答案 2 :(得分:0)

问题是关于 Django 1.11 的。事情发生了变化,因为 Django 3.1 中有一个 SearchHeadline 类。

我没有注意到 Stack Overflow 中有很多关于此的代码,因此请考虑以下事项:

  1. 假设 models.py 包含一个 Article 模型。它有两个 TextField('headline'/'content')和一个 SearchVectorField 用于内容:

    from django.contrib.postgres.search import SearchVector, SearchVectorField, SearchHeadline
    from django.db.models import F, Q
    
    class Article(models.Model):
    headline = models.TextField()
    content = models.TextField()
    content_vector = SearchVectorField(null=True)
    
  2. 在您的控制台/终端中,以下代码将起作用:

    query = "book"
    
    Article.objects
    .annotate(v_head=SearchHeadline(F("content"), query))
    .filter(content_vector=query)
    
  3. 上面有两个部分 - 使用 SearchHeadline 注释 v_head 'column' 的注释,然后是针对“book”查询的过滤器本身。

  4. 假设文本是“Lorem ipsum book lorem ipsum”,输出将是:

    <块引用>

    Lorem ipsum book lorem ipsum。

您可以看到 other similar code on Github