Skip to content

Instantly share code, notes, and snippets.

@michaelkuty
Last active September 9, 2015 15:43
Show Gist options
  • Save michaelkuty/270e7c854b53ef9eccdd to your computer and use it in GitHub Desktop.
Save michaelkuty/270e7c854b53ef9eccdd to your computer and use it in GitHub Desktop.
full implementation bootstrap pagination datatable for openstack horizon
{% load i18n %}
{% with table.needs_form_wrapper as needs_form_wrapper %}
<div class="table_wrapper">
{% if needs_form_wrapper %}<form action="{{ table.get_full_url }}" method="POST">{% csrf_token %}{% endif %}
{% with columns=table.get_columns rows=table.get_rows %}
{% block table %}
<table id="{{ table.name }}" class="table table-bordered table-striped datatable">
<thead>
{% block table_caption %}
<tr class='table_caption'>
<th class='table_header' colspan='{{ columns|length }}'>
<h3 class='table_title'>{{ table }}</h3>
{{ table.render_table_actions }}
</th>
</tr>
{% endblock table_caption %}
{% block table_breadcrumb %}
{% if table.breadcrumb %}
<tr>
<td class="breadcrumb_td" colspan="{{ table.get_columns|length }}">
{{ table.breadcrumb.render }}
</td>
</tr>
{% endif %}
{% endblock table_breadcrumb %}
{% block table_columns %}
{% if not table.is_browser_table %}
<tr>
{% for column in columns %}
<th {{ column.attr_string|safe }}>{{ column }}</th>
{% endfor %}
</tr>
{% endif %}
{% endblock table_columns %}
</thead>
{% block table_body %}
<tbody>
{% for row in rows %}
{{ row.render }}
{% empty %}
<tr class="{% cycle 'odd' 'even' %} empty">
<td colspan="{{ table.get_columns|length }}">{{ table.get_empty_message }}</td>
</tr>
{% endfor %}
</tbody>
{% endblock table_body %}
{% block table_footer %}
{% if table.footer %}
<tfoot>
{% if table.pagination %}
<tr>
<td colspan="{{ table.get_columns|length }}">
<span style="float:right!important;margin-top:9px;" class="table_count">{% blocktrans count counter=rows|length %}Displaying {{ counter }} item{% plural %}Displaying {{ counter }} items{% endblocktrans %}</span>
{% include "pagination.html" %}
</td>
</tr>
{% if table.needs_summary_row %}
<tr class="summation">
{% for column in columns %}
{% if forloop.first %}
<td>{% trans "Summary" %}</td>
{% else %}
<td>{{ column.get_summation|default_if_none:"&ndash;"}}</td>
{% endif %}
{% endfor %}
</tr>
{% endif %}
{% else %}
{% if table.needs_summary_row %}
<tr class="summation">
{% for column in columns %}
{% if forloop.first %}
<td>{% trans "Summary" %}</td>
{% else %}
<td>{{ column.get_summation|default_if_none:"&ndash;"}}</td>
{% endif %}
{% endfor %}
</tr>
{% endif %}
<tr>
<td colspan="{{ table.get_columns|length }}">
<span class="table_count">{% blocktrans count counter=rows|length %}Displaying {{ counter }} item{% plural %}Displaying {{ counter }} items{% endblocktrans %}</span>
{% if table.has_more_data %}
<span class="spacer">|</span>
<a href="?{{ table.get_pagination_string }}">More&nbsp;&raquo;</a>
{% endif %}
</td>
</tr>
{% endif %}
</tfoot>
{% endif %}
{% endblock table_footer %}
</table>
{% endblock table %}
{% endwith %}
{% if needs_form_wrapper %}</form>{% endif %}
</div>
{% endwith %}
class BaseFilterAction(tables.FilterAction):
"""filter action for search in all available columns
.. attribute:: custom_field
Custom field for search. Default is all fields.
"""
needs_preloading = True
custom_field = None #not implemented
def filter(self, table, data, filter_string):
q = filter_string.lower()
def comp(obj):
if isinstance(obj, dict):
for key, value in obj.iteritems():
if q in obj.get(key, "").lower():
return True
if isinstance(obj, object):
for prop in obj._meta.fields:
name = prop.name
if q in str(obj.__dict__[name]):
return True
return False
try:
data = table.get_paginator_data() #all data for table
except AttributeError:
pass
return filter(comp, data)
# -*- coding: UTF-8 -*-
from django.conf import settings
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from horizon import tables
class PaginatedTable(tables.DataTable):
"""You must define a "get_paginator_data" method
`get_paginator_data` must be overwritten and must returns queryset / dataset for paginator
pass
"""
""" Turn off render pagination into template.
.. attribute:: pagination
Turn off render `Show all` into template.
.. attribute:: show_all_url
"""
page = "1"
pagination = True
show_all_url = True
PAGINATION_COUNT = "25"
_paginator = None
def __init__(self, *args, **kwargs):
super(PaginatedTable, self).__init__(*args, **kwargs)
has_get_data = hasattr(self, 'get_paginator_data') and callable(self.get_paginator_data)
if not has_get_data:
cls_name = self.__class__.__name__
raise NotImplementedError('You must define either a "get_paginator_data" '
'method on %s.' % cls_name)
try:
self.PAGINATION_COUNT = settings.PAGINATION_COUNT
except Exception, e:
pass
def get_paginator_data(self):
"""must be overwritten
returns queryset or list dataset for paginator
"""
pass
def get_page(self):
"""returns int page"""
return int(self.page)
def get_page_data(self, page=None):
"""returns data for specific page
default returns for first page
"""
if not self.paginator:
raise RuntimeError('missing paginator instance %s.' % cls_name)
if page:
self.page = page
try:
if not self.page == "all":
objects = self.paginator.page(self.page)
elif self.show_all_url:
objects = self.get_paginator_data()
except EmptyPage:
objects = self.paginator.page(self.paginator.num_pages)
return objects
@property
def paginator(self):
"""returns instance of paginator
"""
if not self._paginator:
try:
self._paginator = Paginator(self.get_paginator_data(), self.PAGINATION_COUNT)
except Exception, e:
raise e
return self._paginator
def previous_page_number(self):
return int(self.page) - 1
def next_page_number(self):
return int(self.page) + 1
def has_previous(self):
if int(self.page) == 1:
return False
return True
def has_next(self):
if (int(self.page) + 1) > self.paginator.num_pages:
return False
return True
def has_more_data(self):
"""turn off horizon default pagination"""
return False
"""
def get_pagination_string(self):
return "page=%s"% self.page
"""
# -*- coding: UTF-8 -*-
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django import http
from django.conf import settings
from django import shortcuts
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from django.forms.models import model_to_dict
from django.views.generic import edit
from horizon import tables
class BaseIndexView(tables.DataTableView):
"""get_data call get_page_data on a table
"""
def get_data(self):
objects = []
table = self.get_table()
page = self.request.GET.get('page', None)
if table:
if page:
try:
objects = table.get_page_data(page=page)
except NotImplementedError, e:
raise e
else:
objects = table.get_page_data() #defaultne 1
return objects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment