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 框架序列化器的主要内容,如果未能解决你的问题,请参考以下文章
DJANGO-天天生鲜项目从0到1-009-搜索功能实现(django-haystack+whoosh+jieba)