diff --git a/bootstrap_pagination/templates/bootstrap_pagination/pager.html b/bootstrap_pagination/templates/bootstrap_pagination/pager-bs3.html
similarity index 79%
rename from bootstrap_pagination/templates/bootstrap_pagination/pager.html
rename to bootstrap_pagination/templates/bootstrap_pagination/pager-bs3.html
index 4fbcf9b..f7e49e4 100644
--- a/bootstrap_pagination/templates/bootstrap_pagination/pager.html
+++ b/bootstrap_pagination/templates/bootstrap_pagination/pager-bs3.html
@@ -4,7 +4,7 @@
{{ previous_label }}
{% else %}
-
+
{{ previous_label }}
{% endif %}
@@ -14,8 +14,8 @@
{{ next_label }}
{% else %}
-
+
{{ next_label }}
{% endif %}
-
+
diff --git a/bootstrap_pagination/templates/bootstrap_pagination/pager-bs4.html b/bootstrap_pagination/templates/bootstrap_pagination/pager-bs4.html
new file mode 100644
index 0000000..28073fb
--- /dev/null
+++ b/bootstrap_pagination/templates/bootstrap_pagination/pager-bs4.html
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/bootstrap_pagination/templates/bootstrap_pagination/pagination.html b/bootstrap_pagination/templates/bootstrap_pagination/pagination-bs3.html
similarity index 100%
rename from bootstrap_pagination/templates/bootstrap_pagination/pagination.html
rename to bootstrap_pagination/templates/bootstrap_pagination/pagination-bs3.html
diff --git a/bootstrap_pagination/templates/bootstrap_pagination/pagination-bs4.html b/bootstrap_pagination/templates/bootstrap_pagination/pagination-bs4.html
new file mode 100644
index 0000000..3260525
--- /dev/null
+++ b/bootstrap_pagination/templates/bootstrap_pagination/pagination-bs4.html
@@ -0,0 +1,76 @@
+{% load bootstrap_pagination %}
+
diff --git a/bootstrap_pagination/templatetags/bootstrap_pagination.py b/bootstrap_pagination/templatetags/bootstrap_pagination.py
index 157db36..49d7255 100755
--- a/bootstrap_pagination/templatetags/bootstrap_pagination.py
+++ b/bootstrap_pagination/templatetags/bootstrap_pagination.py
@@ -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
@@ -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,
@@ -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,
diff --git a/setup.py b/setup.py
index 76d395a..cc4c1b6 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
setup(
name='django-bootstrap-pagination',
- version='1.5.2',
+ version='1.6.0',
keywords="django bootstrap pagination templatetag",
author=u'Jason McClellan',
author_email='jason@jasonmccllelan.net',
@@ -20,9 +20,21 @@
zip_safe=False,
include_package_data=True,
classifiers=[
- "Development Status :: 3 - Alpha",
- "Framework :: Django",
+ "Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
+ "Framework :: Django",
+ "Framework :: Django :: 1.4",
+ "Framework :: Django :: 1.5",
+ "Framework :: Django :: 1.6",
+ "Framework :: Django :: 1.7",
+ "Framework :: Django :: 1.8",
+ "Framework :: Django :: 1.9",
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.2",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
]
)
diff --git a/tests/test_pager.py b/tests/test_pager.py
index 6cb784c..40aff9d 100644
--- a/tests/test_pager.py
+++ b/tests/test_pager.py
@@ -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):
@@ -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')
diff --git a/tests/test_paginate.py b/tests/test_paginate.py
index dcdd590..66ae991 100644
--- a/tests/test_paginate.py
+++ b/tests/test_paginate.py
@@ -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 %}
@@ -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')
diff --git a/tests/test_settings.py b/tests/test_settings.py
index 968e0ad..82c3dae 100644
--- a/tests/test_settings.py
+++ b/tests/test_settings.py
@@ -8,7 +8,12 @@
'bootstrap_pagination',
)
-DATABASES = {}
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': ':memory:',
+ }
+}
MIDDLEWARE_CLASSES = ()
ROOT_URLCONF = 'tests.test_settings.urls'
diff --git a/tests/utils.py b/tests/utils.py
new file mode 100644
index 0000000..a256a56
--- /dev/null
+++ b/tests/utils.py
@@ -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)