6

Websites often allow the user to specify how many items to show per page in a paginated table. Iwould like to do this with django-tables2.

I could add a "Show [ 5 | 10 | 50 ] per page" select box to collect a per_page parameter from the user.

However, the "Previous" and "Next" buttons in the table template are hyperlinks, with a hardcoded value for per_page, e.g.:

<a href="?per_page=5&page=5">Next</a>

I am thinking the only way to make this dynamic would be to use javascript, e.g.:

<span onclick="get_table_page(5)">Next</span>

Where the functions get_table_page() can retrieve the per_page parameter from the select box.

Is that the best way to do it? Or is there a way without javascript?

UPDATE: No answer to the question (how to change per_page for Previous/Next page) but, as accepted answer points out, user can reload the current page with changed per_page parameter, e.g.:

<p>Show [ <a href="{% querystring "per_page"=5  %}">5</a>
        | <a href="{% querystring "per_page"=20 %}">20</a>
        | <a href="{% querystring "per_page"=50 %}">50</a>
        ] Items</p>

With thanks and best wishes

Ivan

Ivan Uemlianin
  • 953
  • 7
  • 21

2 Answers2

5

django-tables2 supports the per_page keyword argument to table.paginate(). If RequestConfig or one of the class based views is used, just adding per_page=20 to the url will make django-tables2 re-render with 20 rows per page.

You can create urls in your custom template using the {% querystring per_page=20 %} tag, which should keep the sorting/filtering intact.

Jieter
  • 4,101
  • 1
  • 19
  • 31
  • Thanks for your comment. The documentation is very clear. Adding or changing the per_page parameter in the url works as expected. However, my question is about enabling the viewer to change the per_page parameter themselves in the browser. In the default template, the Previous and Next buttons are hyperlinks, and the per-page parameters are set server-side before rendering. – Ivan Uemlianin Jun 19 '17 at 08:54
  • Yes, the second part of my comment suggests rendering the links to change the `per_page` parameter. These would result in a reload of the page, with different numbers in the prev/next links. – Jieter Jun 19 '17 at 15:26
  • 1
    I'm afraid I don't follow you. Template tags are rendered on the server. I need the user to be able to change the per_page parameter in the browser. e.g. page loads showing 20 per page; user selects "show 50 per page"; user clicks "Next"; page loads showing next 50 items. I suppose it would be easier to make the "Show [ 5 | 10 | 50 ] items" select box a set of links, so changing the selection would reload the page. – Ivan Uemlianin Jun 20 '17 at 16:32
  • Why is it critical to do it dynamically? If you must have a dropdown, you can also use a form to submit that to the correct url to change the `per_page` argument. – Jieter Jun 21 '17 at 09:04
  • 1
    I've accepted your answer and updated the question to clarify. Thanks. – Ivan Uemlianin Jun 22 '17 at 08:39
1

I don't know how to find the current querystring (with differents parameters) so I wrote in my template :

Show <select id="select_per_page" onchange="perPageChange($(this).val())">
    <option value="10">10</option>
    <option value="25">25</option>
    <option value="50">50</option>
    <option value="100">100</option>
</select> items

and with a few javascript :

<script>
    function perPageChange(per_page)
    {
        /* per_page in querystring : replace the value in the current url */
        if (location.href.indexOf('per_page=') > 0)
            url = location.href.replace(/(per_page=)[^\&]+/, '$1' + per_page)
        else
        {
        /* per_page not in querystring */
            /* is there a parameter in querystring */
            if (location.href.indexOf('?') > 0)
                addStr = '&'
            else
                addStr = '?'
            addStr += 'per_page=' + per_page
            url = location.href + addStr
        }
        /* reload the page */
        location.href = url;
    }

    /* to select the correct option in the select */
    $('#select_per_page').val({{ table.page.object_list|length }});
</script>