首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python elasticsearch-dsl django分页

Python elasticsearch-dsl django分页
EN

Stack Overflow用户
提问于 2016-03-09 00:41:59
回答 4查看 6.2K关注 0票数 10

如何在elasticsearch上使用django分页。我的代码:

代码语言:javascript
复制
query = MultiMatch(query=q, fields=['title', 'body'], fuzziness='AUTO')

s = Search(using=elastic_client, index='post').query(query).sort('-created_at')
response = s.execute()

// this always returns page count 1
paginator = Paginator(response, 100)
page = request.GET.get('page')
try:
    posts = paginator.page(page)
except PageNotAnInteger:
    posts = paginator.page(1)
except EmptyPage:
    posts = paginator.page(paginator.num_pages)

有什么解决办法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-03-09 13:09:20

我在这个链接上找到了这个分页器

代码语言:javascript
复制
from django.core.paginator import Paginator, Page

class DSEPaginator(Paginator):
    """
    Override Django's built-in Paginator class to take in a count/total number of items;
    Elasticsearch provides the total as a part of the query results, so we can minimize hits.
    """
    def __init__(self, *args, **kwargs):
        super(DSEPaginator, self).__init__(*args, **kwargs)
        self._count = self.object_list.hits.total

    def page(self, number):
        # this is overridden to prevent any slicing of the object_list - Elasticsearch has
        # returned the sliced data already.
        number = self.validate_number(number)
        return Page(self.object_list, number, self)

然后我用:

代码语言:javascript
复制
    q = request.GET.get('q', None)
    page = int(request.GET.get('page', '1'))
    start = (page-1) * 10
    end = start + 10

    query = MultiMatch(query=q, fields=['title', 'body'], fuzziness='AUTO')
    s = Search(using=elastic_client, index='post').query(query)[start:end]
    response = s.execute()

    paginator = DSEPaginator(response, settings.POSTS_PER_PAGE)
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

这样它工作得很完美..。

票数 14
EN

Stack Overflow用户

发布于 2018-01-15 14:17:20

根据Danielle的建议,我还创建了一个搜索结果的代理,它与最新版本的django-elasticsearch-dsl==0.4.4很好地兼容。

代码语言:javascript
复制
from django.utils.functional import LazyObject

class SearchResults(LazyObject):
    def __init__(self, search_object):
        self._wrapped = search_object

    def __len__(self):
        return self._wrapped.count()

    def __getitem__(self, index):
        search_results = self._wrapped[index]
        if isinstance(index, slice):
            search_results = list(search_results)
        return search_results

然后您可以在搜索视图中使用它,如下所示:

代码语言:javascript
复制
paginate_by = 20
search = MyModelDocument.search()
# ... do some filtering ...
search_results = SearchResults(search)

paginator = Paginator(search_results, paginate_by)
page_number = request.GET.get("page")
try:
    page = paginator.page(page_number)
except PageNotAnInteger:
    # If page parameter is not an integer, show first page.
    page = paginator.page(1)
except EmptyPage:
    # If page parameter is out of range, show last existing page.
    page = paginator.page(paginator.num_pages)

Django的LazyObject代理分配给_wrapped属性的对象中的所有属性和方法。我正在重写Django的分页器所需的几个方法,但不要对Search()实例进行越界操作。

票数 1
EN

Stack Overflow用户

发布于 2019-10-22 16:57:31

一个非常简单的解决方案是使用MultipleObjectMixin并通过覆盖它在get_queryset()中提取您的弹性结果。在本例中,如果添加paginate_by属性,Django将处理分页本身。

应该是这样的:

代码语言:javascript
复制
class MyView(MultipleObjectMixin, ListView):
    paginate_by = 10

    def get_queryset(self):
        object_list = []
        """ Query Elastic here and return the response data in `object_list`.
            If you wish to add filters when querying Elastic,
            you can use self.request.GET params here. """
        return object_list

注:,上面的代码很宽泛,与我自己的情况不同,所以我不能保证它能工作。我使用了类似的解决方案,继承了其他Mixins,重写了get_queryset(),并利用了Django在分页中构建的特性--它对我非常有用。因为这是一个简单的修复,所以我决定在这里发布一个类似的例子。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35880868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档