Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-templatesdjango-admin

Overriding django admin pagination along with url parameters


I would like to implement custom pagination for my admin panel.

My url looks like the following: http://localhost:8000/admin/items/?group_id=20

On this URL I do some work to filter the results using the parameter group_id (by overriding get_changelist method).

The page results are corrects, the problem is my pagination ending up like this http://localhost:8000/admin/items/?p=1 whereas I would like the URL to be http://localhost:8000/admin/items/?group_id=20&p=1 and keep the parameter.

Basically I want the same result as How to paginate Django with other get variables? but using Django admin.

How can I keep the parameter along with the pagination?

I've tried overriding pagination.html file but without any success.

Thank you.

Edit

I've tried overriding pagination.html but request.GET.items is still empty (even if my settings file is well configured)

{% load admin_list %}
{% load i18n %}
{% load content_extras %}
<p class="paginator">
{% if pagination_required %}
    {% for i in page_range %}
        <a href="?p={{ i }}{% for key, value in request.GET.items %}{% if key != 'p' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">{{ i }}</a>
    {% endfor %}
{% endif %}
{{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
{% if show_all_url %}<a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
</p>

Solution

  • FOUND A SOLUTION:

    1/ Override changelist_view on admin.py and pass the extra data

    def changelist_view(self, request, extra_context=""):
        response = super(ItemAdmin, self).changelist_view(request, extra_context)
    
        group_id = request.GET.get('group_id', None)
    
        if group_id:
            extra_context = {
                'group_id': group_id,
            }
            response.context_data.update(extra_context)
    
        return TemplateResponse(request, "admin/changelist.html", response.context_data)
    

    2/ Create changelist.html file based on django admin template (copy/paste)

    Add {% load content_extras %} at the top of the file (line 3)

    Change line {% block pagination %}{% pagination cl %}{% endblock %} with {% block pagination %}{% custom_pagination cl %}{% endblock %}

    3/ Create content_extras.py under templatetags folder and write custom_pagination function

    from django import template
    from django.contrib.admin.templatetags import admin_list
    
    register = template.Library()
    
    
    @register.inclusion_tag('admin/pagination.html', takes_context=True)
    def custom_pagination(context, cl):
        pagination = admin_list.pagination(cl)
        if 'group_id' in context:
            params = (('group_id', context['group_id']),)
            pagination['params'] = params
        return pagination
    

    4/ Create pagination.html (same location as changelist.html)

    {% load admin_list %}
    {% load i18n %}
    {% load content_extras %}
    <p class="paginator">
    {% if pagination_required %}
        {% for i in page_range %}
            <a href="?p={{ i }}{% for key, value in params %}{% if key != 'p' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">{{ i }}</a>
        {% endfor %}
    {% endif %}
    {{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
    {% if show_all_url %}<a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
    {% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
    </p>