Django Haystack 结果到 Django Rest 框架序列化器

Posted

技术标签:

【中文标题】Django Haystack 结果到 Django Rest 框架序列化器【英文标题】:Django Haystack Results to Django Rest Framework Serializer 【发布时间】:2013-11-28 23:22:37 【问题描述】:

我正在尝试使用 Django Haystack 进行搜索,然后在检索结果时,我需要将这些结果传递给我的 Django Rest Framework 序列化程序。

Django Rest Framework serializers.ModelSerializer 要求为序列化程序发送对象查询集,以便能够序列化这些对象及其数据库字段。

当我创建我的 API 视图并使用搜索来获取结果时,haystack 返回一个 searchqueryset。

如何在不执行以下操作的情况下将此 searchqueryset 放入 django 查询集:

article_queryset = Article.objects.filter(id__in=[i.object for i in searchqueryset])

如您所想,有时搜索可以返回超过 1000 个搜索结果,这意味着上述方法的效率非常低。

现在,Django rest 框架允许我对返回的对象进行分页。我在每页上按 30 个对象进行分页。我怎么可能对我的 Haystack 搜索查询集做同样的事情?

任何关于如何使用 Haystack 和 Django Rest 框架的建议或想法都会很棒。其他人如何做类似事情的例子也很酷:)

【问题讨论】:

您使用的是什么搜索后端?如果您使用elasticsearch,您可能不需要采取额外的步骤,因为在elasticsearch 中的结果已经在_source 字段中以json 形式返回。 【参考方案1】:

您可以使用 Haystack 的 SearchView(而不是 DRF 视图),它会公开页面对象以进行分页。然后你可以把它传递给你的序列化器。

例如不久前,我正在处理需要在当前 html 页面上呈现结果的 json 对象的东西,所以我编写了一个过滤器标记来执行此操作(我们使用 FacetedSearchView 作为 UI,而 DRF 用于更通用的 RESTful API) .在模板中这样调用:

var articlesJson =  page.object_list|article_jsonify 

实际过滤标签:

import collections
from django.template import Library
from django.utils.safestring import mark_safe
from rest_framework.renderers import JSONRenderer

register = Library()


def article_jsonify(object):
    if isinstance(object, collections.Iterable):
        many = True
        ids = [obj.object.id for obj in object]
    else:
        many = False
        ids = [object.id]

    articles = Article.objects.filter(pk__in=ids)
    serializer = ArticleSerializer(articles, many=many)
    content = JSONRenderer().render(serializer.data)
    return mark_safe(content)

register.filter('article_jsonify', article_jsonify)

您还可以编写一个继承自 generics.ListAPIView 的视图并覆盖 get_queryset 方法,您可以将请求的查询参数传递给 SearchQuerySet,然后使用 Serializer 将其输出。更多信息在这里:

http://www.django-rest-framework.org/api-guide/filtering

当然,您可能无法以这种方式使用 ModelSerializer,除非您执行您提到的操作。但是 DRF 有一个在查询集上使用分页器的示例,如下所示:

http://www.django-rest-framework.org/api-guide/pagination#paginating-querysets

更新 我最终使用了一个 DRF 视图,该视图使用 Haystack SearchQuerySet 作为查询集,然后将其传递给 Paginator。这是一个简化的示例(我相信它可以简化一些),但我希望它可以帮助某人入门。

class ArticleList(ListCreateAPIView):

    """
    List, Create files
    """
    model = Article

    def get(self, request, *args, **kwargs):
        # simplified filtering of an SQS
        q = request.get('q', '')
        sqs = SearchQuerySet().filter(content=Clean(q))
        paginator = Paginator(sqs, 20)

        page = request.QUERY_PARAMS.get('page')
        try:
            articles = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page
            articles = paginator.page(1)
        except PageNotAnInteger:
            # If page is out of range, deliver last page
            articles = paginator.page(paginator.num_pages)

        serializer_context = 'request': request
        serializer = PaginatedArticleSerializer(articles, context=serializer_context)

        return Response(serializer.data)

class ArticleSerializer(serializers.ModelSerializer):

    """
    Base Article Serializer
    """

    class Meta:
        model = Article

class PaginatedArticleSerializer(pagination.PaginationSerializer):

    """
    Serializes page objects of article querysets.
    """
    start_index = serializers.SerializerMethodField('get_start_index')
    end_index = serializers.SerializerMethodField('get_end_index')
    num_pages = serializers.Field(source='paginator.num_pages')

    class Meta:
        object_serializer_class = ArticleSerializer

    def get_start_index(self, page):
        return page.start_index()

    def get_end_index(self, page):
        return page.end_index()

    def get_curr_page(self, page):
        return page.number

【讨论】:

我不明白这段代码如何使用需要 Article 模型实例的序列化程序序列化 Haystacks SearchResults 的实例。我正在尝试为一个简单的 api 端点实现一个简单版本,该端点将输出 JSON,其中包含与搜索结果关联的序列化模型实例。 SearchResult 和 SearchQuerySet 在 Django 的 Model 和 Queryset 类之后建模(没有双关语),因此它们具有相似的行为和接口。我相信它对我有用,如果我必须在序列化程序中做任何特别的事情,我会看看并告诉你。

以上是关于Django Haystack 结果到 Django Rest 框架序列化器的主要内容,如果未能解决你的问题,请参考以下文章

遇到502重新安装django-haystack

DJANGO-天天生鲜项目从0到1-009-搜索功能实现(django-haystack+whoosh+jieba)

重建索引时,带有 Elasticsearch 的 Django haystack 找不到数据库

Django Haystack 全文检索与关键词高亮

Django Haystack 全文检索与关键词高亮

使用haystack实现Django的全文搜索 -- Elasticsearch搜索引擎