Skip to content

Instantly share code, notes, and snippets.

@coderanger
Created August 31, 2010 22:45
Show Gist options
  • Save coderanger/559911 to your computer and use it in GitHub Desktop.
Save coderanger/559911 to your computer and use it in GitHub Desktop.
Pagination for admin inlines
class MyInline(admin.TabularInline):
model = MyModel
extra = 0
template = 'admin/edit_inline/list.html'
def get_formset(self, request, obj=None, **kwargs):
FormSet = super(ActivationKeyInline, self).get_formset(request, obj, **kwargs)
class NewFormSet(FormSet):
def _construct_forms(self, *args, **kwargs):
qs = self.get_queryset()
paginator = Paginator(qs, 20)
try:
page_num = int(request.GET.get('page', '1'))
except ValueError:
page_num = 1
try:
page = paginator.page(page_num)
except (EmptyPage, InvalidPage):
page = paginator.page(paginator.num_pages)
self.paginator = paginator
self.page = page
self._queryset = page.object_list
self.max_num = len(page.object_list)
return super(NewFormSet, self)._construct_forms(*args, **kwargs)
return NewFormSet
@mc3
Copy link

mc3 commented Oct 9, 2012

Anybody got a template working for this?
I looked around in admin sources and it seems that much more work is required to get the above snippet working.
Any hints?

@kclay
Copy link

kclay commented Mar 20, 2013

Any template for this one??

@jimivdw
Copy link

jimivdw commented Jun 27, 2013

After a bit of looking around on the web I came up with the following template:

{% with inline_admin_formset.formset.page as page_obj %}
  <p class="paginator">
    {% if page_obj.has_previous %}
      <a href="?page={{ page_obj.previous_page_number }}">{% trans 'previous' %}</a>
    {% endif %}

    {% if page_obj.number|add:"-5" > 0 %}
      <a href="?page=1">1</a>
    {% endif %}

    {% if page_obj.number|add:"-5" > 1 %}
      <span>&hellip;</span>
    {% endif %}

    {% for page_num in page_obj.paginator.page_range %}
      {% if page_obj.number == page_num %}
        <span class="this-page">{{ page_num }}</span>
      {% else %}
        {% if page_num > page_obj.number|add:"-5" and page_num < page_obj.number|add:"5" %}
          <a href="?page={{ page_num }}">{{ page_num }}</a>
        {% endif %}
      {% endif %}
    {% endfor %}

    {% if page_obj.number|add:"5" < page_obj.paginator.num_pages %}
      <span>&hellip;</span>
    {% endif %}

    {% if page_obj.number|add:"4" < page_obj.paginator.num_pages %}
      <a href="?page={{ page_obj.paginator.num_pages }}">{{ page_obj.paginator.num_pages }}</a>
    {% endif %}

    {% if page_obj.has_next %}
      <a href="?page={{ page_obj.next_page_number }}">{% trans 'next' %}</a>
    {% endif %}
  </p>
{% endwith %}

Insert this after the </table>, before the </fieldset> in a copy of the original tabular.html (https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/edit_inline/tabular.html), for this gist, saved in templates/admin/edit_inline/list.html.

It's not perfect (feel free to improve :-) ), but definitely working for me.

PS: the CSS for the paginator is by default found in admin/css/changelists.css, if you need it.

@kewp
Copy link

kewp commented Sep 27, 2018

Is it suppose to say ActivationKeyInline ?

@kewp
Copy link

kewp commented Sep 27, 2018

This is for an old version of Django (1.5). For later versions use this darklow/django-suit#65 (comment)

@slem0ine
Copy link

And for Django 2.2? :)

@the-vishal
Copy link

the-vishal commented Mar 25, 2020

For any version of Django, follow these steps:

  1. visit this file : python3.7/site-packages/django/contrib/admin/templates/admin/edit_inline/tabular.html make a copy of it in your app/templates/admin/edit_inline/anyname.html

between </table> and </fieldset> tag add :

   <style>
    .dark {
      /*background-color: #417690;*/
      background-color: #FFFFFF;
      border: none;
      color: #666;
      padding: 5px 10px;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 12px;
      margin: 4px 2px;
      cursor: pointer;
    }
    .light {
      background-color: #008CBA;
      border: none;
      color: white;
      padding: 5px 10px;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 12px;
      margin: 4px 2px;
      cursor: pointer;
    }

  </style>
   <div>
   {% with inline_admin_formset.formset.page as page_obj %}
    <p class="paginator">
      {% if page_obj.previous_page_number > 1 %}
        <a href="?page={{ page_obj.previous_page_number|add:'-1' }}">{% trans 'previous' %}</a>
      {% endif %}

      {% if page_obj.number|add:"-5" > 0 %}
        <a href="?page=0">1</a>
      {% endif %}

      {% if page_obj.number|add:"-5" > 1 %}
        <span>&hellip;</span>
      {% endif %}

      {% for page_num in page_obj.paginator.page_range %}
        {% if page_obj.number == page_num %}
          <span class="dark">{{ page_num|add:"-1" }}</span>
        {% else %}
          {% if page_num > page_obj.number|add:"-5" and page_num < page_obj.number|add:"5" %}
            <a class="light" style="color:white" href="?page={{ page_num|add:'-1' }}">{{ page_num|add:"-1" }}</a>
          {% endif %}
        {% endif %}
      {% endfor %}

      {% if page_obj.number|add:"5" < page_obj.paginator.num_pages %}
        <span>&hellip;</span>
      {% endif %}

      {% if page_obj.number|add:"4" < page_obj.paginator.num_pages %}
        <a href="?page={{ page_obj.paginator.num_pages }}">{{ page_obj.paginator.num_pages }}</a>
      {% endif %}

      {% if page_obj.next_page_number < page_obj.paginator.num_pages|add:'1' %}
        <a href="?page={{ page_obj.next_page_number|add:'-1' }}">{% trans 'next' %}</a>
      {% endif %}
      <span class='dark'>{{ page_obj.paginator.count }} Queries</span>
    </p>
  {% endwith %}
  </div> 

2.Go to your admin.py file:

from django.contrib.admin.views.main import ChangeList
from django.core.paginator import EmptyPage, InvalidPage, Paginator

class InlineChangeList(object):
    can_show_all = True
    multi_page = True
    get_query_string = ChangeList.__dict__['get_query_string']

    def __init__(self, request, page_num, paginator):
        self.show_all = 'all' in request.GET
        self.page_num = page_num
        self.paginator = paginator
        self.result_count = paginator.count
        self.params = dict(request.GET.items())


class MyInline(admin.TabularInline):
	per_page = 10
	template = 'admin/edit_inline/anyname.html'
	model = Mymodel
	extra = 0
	can_delete = False

	def get_formset(self, request, obj=None, **kwargs):
	    formset_class = super(MyInline, self).get_formset(
	        request, obj, **kwargs)
	    class PaginationFormSet(formset_class):
	        def __init__(self, *args, **kwargs):
	            super(PaginationFormSet, self).__init__(*args, **kwargs)

	            qs = self.queryset
	            paginator = Paginator(qs, self.per_page)
	            try:
	                page_num = int(request.GET.get('page', ['0'])[0])
	            except ValueError:
	                page_num = 0

	            try:
	                page = paginator.page(page_num + 1)
	            except (EmptyPage, InvalidPage):
	                page = paginator.page(paginator.num_pages)

	            self.page = page
	            self.cl = InlineChangeList(request, page_num, paginator)
	            self.paginator = paginator

	            if self.cl.show_all:
	                self._queryset = qs
	            else:
	                self._queryset = page.object_list

	    PaginationFormSet.per_page = self.per_page
	    return PaginationFormSet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment