def connection_from_cursor_paginated(queryset,
                                     connection_type,
                                     edge_type,
                                     pageinfo_type,
                                     page_query=None):
    """Create a Connection object from a queryset, using CursorPaginator"""
    paginator = CursorPaginator(queryset, queryset.query.order_by)
    if page_query is None:
        page_query = PageQuery()
    page = paginator.page(**attr.asdict(page_query))

    edges = []
    for item in list(page):
        edge = edge_type(node=item, cursor=paginator.cursor(item))
        edges.append(edge)

    if page:
        page_info = pageinfo_type(
            start_cursor=paginator.cursor(edges[0].node),
            end_cursor=paginator.cursor(edges[-1].node),
            has_previous_page=page.has_previous,
            has_next_page=page.has_next,
        )
    else:
        page_info = pageinfo_type(
            start_cursor=None,
            end_cursor=None,
            has_previous_page=False,
            has_next_page=False,
        )

    return connection_type(
        edges=edges,
        page_info=page_info,
    )
Exemple #2
0
 def test_reverse_order(self):
     paginator = CursorPaginator(Post.objects.all(), ('-created', '-name'))
     previous_page = paginator.page(first=2)
     self.assertSequenceEqual(previous_page, [self.items[3], self.items[2]])
     cursor = paginator.cursor(previous_page[-1])
     page = paginator.page(first=2, after=cursor)
     self.assertSequenceEqual(page, [self.items[1], self.items[0]])
Exemple #3
0
def search(user_id, search_term, before=None, after=None):
    """Offload the expensive part of search to avoid blocking the web interface"""
    if not search_term:
        return {
            "results": [],
            "has_next": False
        }

    if before and after:
        raise ValueError("You can't do this.")

    email_subquery = models.Email.objects.viewable(user_id)
    inbox_subquery = models.Inbox.objects.viewable(user_id)
    search_qs = watson_search.search(search_term, models=(email_subquery, inbox_subquery))

    page_kwargs = {
        "after": after,
        "before": before,
    }
    if before:
        page_kwargs["last"] = SEARCH_PAGE_SIZE
    else:
        page_kwargs["first"] = SEARCH_PAGE_SIZE

    paginator = CursorPaginator(search_qs, ordering=('-watson_rank', '-id'))

    page = paginator.page(**page_kwargs)
    results = {
        "results": [p.id for p in page],
        "has_next": page.has_next,
        "has_previous": page.has_previous,
    }

    if len(results["results"]) > 0:
        results["last"] = paginator.cursor(page[-1])
        results["first"] = paginator.cursor(page[0])

    key = create_search_cache_key(user_id, search_term, before, after)
    cache.set(key, results, SEARCH_TIMEOUT)

    return results
def chunked_queryset_iterator(queryset, size, *, ordering=('id', )):
    pager = CursorPaginator(queryset, ordering)
    after = None
    while True:
        page = pager.page(after=after, first=size)
        if page:
            yield from page.items
        else:
            return
        if not page.has_next:
            break
        after = pager.cursor(instance=page[-1])
def ApiListView(request):
    params = request.GET
    queryset = Video.objects.all().order_by('-published_at')
    page_size = 10
    paginator = CursorPaginator(queryset, ordering=['-id'])
    if 'before' in params:
        before = params['before']
        page = paginator.page(first=page_size, before=before)
    elif 'after' in params:
        after = params['after']
        page = paginator.page(first=page_size, after=after)
    else:
        page = paginator.page(first=page_size, after=None)
    data = {
        'objects': [VideoSerializer(p).data for p in page],
        'has_next_page': page.has_next,
        'has_previous_page': page.has_previous,
        'last_cursor': paginator.cursor(page[-1]),
        'first_cursor': paginator.cursor(page[0])
    }
    return JsonResponse(data)
Exemple #6
0
def search(user_id, search_term, before=None, after=None):
    """Offload the expensive part of search to avoid blocking the web interface"""
    if not search_term:
        return {"results": [], "has_next": False}

    if before and after:
        raise ValueError("You can't do this.")

    email_subquery = models.Email.objects.viewable(user_id)
    inbox_subquery = models.Inbox.objects.viewable(user_id)
    search_qs = watson_search.search(search_term,
                                     models=(email_subquery, inbox_subquery))

    page_kwargs = {
        "after": after,
        "before": before,
    }
    if before:
        page_kwargs["last"] = SEARCH_PAGE_SIZE
    else:
        page_kwargs["first"] = SEARCH_PAGE_SIZE

    paginator = CursorPaginator(search_qs, ordering=('-watson_rank', '-id'))

    page = paginator.page(**page_kwargs)
    results = {
        "results": [p.id for p in page],
        "has_next": page.has_next,
        "has_previous": page.has_previous,
    }

    if len(results["results"]) > 0:
        results["last"] = paginator.cursor(page[-1])
        results["first"] = paginator.cursor(page[0])

    key = create_search_cache_key(user_id, search_term, before, after)
    cache.set(key, results, SEARCH_TIMEOUT)

    return results
Exemple #7
0
def _chunked_queryset_iterator(queryset, size, *, ordering=('id', )):
    """
    Split a queryset into chunks.
    This can be used instead of `queryset.iterator()`,
    so `.prefetch_related()` also works
    Note::
    The ordering must uniquely identify the object,
    and be in the same order (ASC/DESC). See https://github.com/photocrowd/django-cursor-pagination
    """
    pager = CursorPaginator(queryset, ordering)
    after = None
    while True:
        page = pager.page(after=after, first=size)
        if page:
            yield from page.items
        else:
            return
        if not page.has_next:
            break
        # take last item, next page starts after this.
        after = pager.cursor(instance=page[-1])