Skip to content
This repository has been archived by the owner on Apr 17, 2021. It is now read-only.

Commit

Permalink
Intial attempt at supporting bootstrap-v4 (alpha)
Browse files Browse the repository at this point in the history
  • Loading branch information
kvdveer committed Feb 17, 2016
1 parent 443ea69 commit 0c03009
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<a title="{{ previous_title }}" href="{{ previous_page_url|default:"#"|escape }}">{{ previous_label }}</a>
</li>
{% else %}
<li class="{% if not centered %} next{% endif %} disabled">
<li class="{% if not centered %}previous{% endif %} disabled">
<span title="{{ previous_title }}">{{ previous_label }}</span>
</li>
{% endif %}
Expand All @@ -14,8 +14,8 @@
<a title="{{ next_title }}" href="{{ next_page_url|default:"#"|escape }}">{{ next_label }}</a>
</li>
{% else %}
<li title="{{ next_title }}" class="{% if not centered %} next{% endif %} disabled">
<li title="{{ next_title }}" class="{% if not centered %}next{% endif %} disabled">
<span>{{ next_label }}</span>
</li>
{% endif %}
</ul>
</ul>
23 changes: 23 additions & 0 deletions bootstrap_pagination/templates/bootstrap_pagination/pager-bs4.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<nav>
<ul class="pager">
{% if page.has_previous %}
<li{% if not centered %} class="pager-prev"{% endif %}>
<a title="{{ previous_title }}" href="{{ previous_page_url|default:"#"|escape }}">{{ previous_label }}</a>
</li>
{% else %}
<li class="{% if not centered %} pager-prev{% endif %} disabled">
<span title="{{ previous_title }}">{{ previous_label }}</span>
</li>
{% endif %}

{% if page.has_next %}
<li{% if not centered %} class="pager-next"{% endif %}>
<a title="{{ next_title }}" href="{{ next_page_url|default:"#"|escape }}">{{ next_label }}</a>
</li>
{% else %}
<li title="{{ next_title }}" class="{% if not centered %} pager-next{% endif %} disabled">
<span>{{ next_label }}</span>
</li>
{% endif %}
</ul>
</nav>
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{% load bootstrap_pagination %}
<nav>
<ul class="pagination{% if size == "small" %} pagination-sm{% endif %}{% if size == "large" %} pagination-lg{% endif %}{% block extra_classes %}{% endblock %}">
{% if show_first_last %}
{% if not page.has_previous %}
<li class="disabled page-item">
<span aria-hidden="true" title="First Page">{{ first_label }}</span>
<span class="sr-only">First Page</span>
</li>
{% else %}
<li class="page-item">
<a title="First Page" href="{{ first_page_url|default:"#"|escape }}">
<span aria-hidden="true">{{ first_label }}</span>
<span class="sr-only">First Page</span>
</a>
</li>
{% endif %}
{% endif %}
{% if show_prev_next %}
{% if not page.has_previous %}
<li class="disabled page-item">
<span aria-hidden="true" title="Previous Page">{{ previous_label }}</span>
<span class="sr-only">Previous Page</span>
</li>
{% else %}
<li class="page-item">
<a title="Previous Page" href="{{ previous_page_url|default:"#"|escape }}">
<span aria-hidden="true">{{ previous_label }}</span>
<span class="sr-only">Previous Page</span>
</a>
</li>
{% endif %}
{% endif %}
{% for pagenum, index_range, url in page_urls %}
{% if page.number == pagenum %}
<li class="active">
<span title="Current Page">{% if show_index_range %} {{ index_range }} {% else %} {{ pagenum }} {%endif %}</span>
</li>
{% else %}
<li class="page-item">
<a title="Page {{ pagenum }} of {{ page.paginator.num_pages }}" href="{{ url|escape }}">{% if show_index_range %} {{ index_range }} {% else %} {{ pagenum }} {%endif %}</a>
</li>
{% endif %}
{% endfor %}
{% if show_prev_next %}
{% if not page.has_next %}
<li class="disabled page-item">
<span aria-hidden="true" title="Next Page">{{ next_label }}</span>
<span class="sr-only">Next Page</span>
</li>
{% else %}
<li class="page-item">
<a title="Next Page" href="{{ next_page_url|default:"#"|escape }}">
<span aria-hidden="true">{{ next_label }}</span>
<span class="sr-only">Next Page</span>
</a>
</li>
{% endif %}
{% endif %}
{% if show_first_last %}
{% if not page.has_next %}
<li class="disabled page-item">
<span aria-hidden="true" title="Last Page">{{ last_label }}</span>
<span class="sr-only">Last Page</span>
</li>
{% else %}
<li class="page-item">
<a title="Last Page" href="{{ last_page_url|default:"#"|escape }}">
<span aria-hidden="true">{{ last_label }}</span>
<span class="sr-only">Last Page</span>
</a>
</li>
{% endif %}
{% endif %}
</ul>
</nav>
17 changes: 15 additions & 2 deletions bootstrap_pagination/templatetags/bootstrap_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ def get_page_url(page_num, current_app, url_view_name, url_extra_args, url_extra
return url


def get_bootstrap_version():
"""Helper version to determine the configured version of bootstrap."""
version = getattr(settings, 'BOOTSTRAP_VERSION', 3)
version = int(version)

# Clap version between supported versions
return max(3, min(version, 4))


class BootstrapPagerNode(Node):
def __init__(self, page, kwargs):
self.page = page
Expand Down Expand Up @@ -105,7 +114,9 @@ def render(self, context):
if page.has_next():
next_page_url = get_page_url(page.next_page_number(), context.current_app, url_view_name, url_extra_args, url_extra_kwargs, url_param_name, url_get_params, url_anchor)

return get_template("bootstrap_pagination/pager.html").render(
template = "bootstrap_pagination/pager-bs%i.html" % get_bootstrap_version()

return get_template(template).render(
Context({
'page': page,
'previous_label': previous_label,
Expand Down Expand Up @@ -220,7 +231,9 @@ def render(self, context):
if page.has_next():
next_page_url = get_page_url(page.next_page_number(), context.current_app, url_view_name, url_extra_args, url_extra_kwargs, url_param_name, url_get_params, url_anchor)

return get_template("bootstrap_pagination/pagination.html").render(
template = "bootstrap_pagination/pagination-bs%i.html" % get_bootstrap_version()

return get_template(template).render(
Context({
'page': page,
'size': size,
Expand Down
22 changes: 22 additions & 0 deletions tests/test_pager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import django.http
from django.core.paginator import Paginator

from tests.utils import override_settings


class PagerTestCase(unittest.TestCase):
def test_example(self):
Expand All @@ -29,3 +31,23 @@ def test_example(self):
'request': django.http.HttpRequest()})
html = lxml.html.fragment_fromstring(template.render(c))
self.assertEqual(html.get('class'), 'pager')

@override_settings(BOOTSTRAP_VERSION=4)
def test_bs4(self):
template = get_template_from_string("""
{% load bootstrap_pagination %}
{% bootstrap_pager page_obj %}
""")

objects = ["obj%02x" % idx
for idx in range(30)]

paginator = Paginator(objects, 10)

c = Context({'page_obj': paginator.page(2),
'request': django.http.HttpRequest()})
html = lxml.html.fragment_fromstring(template.render(c))

self.assertEqual(
html.cssselect('nav>ul.pager>li>a')[0].text.strip(),
'Previous Page')
23 changes: 23 additions & 0 deletions tests/test_paginate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
import django.http
from django.core.paginator import Paginator

from tests.utils import override_settings


class PaginateTestCase(unittest.TestCase):

def test_example(self):
template = get_template_from_string("""
{% load bootstrap_pagination %}
Expand All @@ -32,3 +35,23 @@ def test_example(self):
self.assertEqual(
html.cssselect('[title=\"Current Page\"]')[0].text.strip(),
'2')

@override_settings(BOOTSTRAP_VERSION=4)
def test_bs4(self):
template = get_template_from_string("""
{% load bootstrap_pagination %}
{% bootstrap_paginate page_obj range=10 %}
""")

objects = ["obj%02x" % idx
for idx in range(30)]

paginator = Paginator(objects, 10)

c = Context({'page_obj': paginator.page(2),
'request': django.http.HttpRequest()})
html = lxml.html.fragment_fromstring(template.render(c))

self.assertEqual(
html.cssselect('nav>ul.pagination>li>span[title=\"Current Page\"]')[0].text.strip(),
'2')
7 changes: 6 additions & 1 deletion tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
'bootstrap_pagination',
)

DATABASES = {}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
MIDDLEWARE_CLASSES = ()

ROOT_URLCONF = 'tests.test_settings.urls'
Expand Down
64 changes: 64 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from functools import wraps

from django.conf import UserSettingsHolder, settings
try:
from django.test.signals import setting_changed
except ImportError:
setting_changed = None


# This was taken from django 1.9 django.tests.utils, and adapted to be
# compatible with a wider range of django versions.
class override_settings(object):
"""
Acts as either a decorator, or a context manager. If it's a decorator it
takes a function and returns a wrapped function. If it's a contextmanager
it's used with the ``with`` statement. In either event entering/exiting
are called before and after, respectively, the function/block is executed.
"""
def __init__(self, **kwargs):
self.options = kwargs

def __enter__(self):
self.enable()

def __exit__(self, exc_type, exc_value, traceback):
self.disable()

def __call__(self, test_func):
@wraps(test_func)
def inner(*args, **kwargs):
with self:
return test_func(*args, **kwargs)
return inner

def save_options(self, test_func):
if test_func._overridden_settings is None:
test_func._overridden_settings = self.options
else:
# Duplicate dict to prevent subclasses from altering their parent.
test_func._overridden_settings = dict(
test_func._overridden_settings, **self.options)

def enable(self):
# Changing installed apps cannot be done in a backward-compatible way
assert 'INSTALLED_APPS' not in self.options

override = UserSettingsHolder(settings._wrapped)
for key, new_value in self.options.items():
setattr(override, key, new_value)
self.wrapped = settings._wrapped
settings._wrapped = override
for key, new_value in self.options.items():
if setting_changed:
setting_changed.send(sender=settings._wrapped.__class__,
setting=key, value=new_value, enter=True)

def disable(self):
settings._wrapped = self.wrapped
del self.wrapped
for key in self.options:
new_value = getattr(settings, key, None)
if setting_changed:
setting_changed.send(sender=settings._wrapped.__class__,
setting=key, value=new_value, enter=False)

0 comments on commit 0c03009

Please sign in to comment.