Django Haystack结果为Django Rest Framework Serializer

时间:2013-11-15 14:24:29

标签: django django-haystack django-rest-framework

我正在尝试使用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 searchqueryset做同样的事情?

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

1 个答案:

答案 0 :(得分:8)

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

E.G。一段时间后,我正在研究在当前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有一个在查询集上使用paginator的示例:

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