├── .coveragerc
├── .gitignore
├── .travis.yml
├── LICENSE
├── MANIFEST.in
├── README.md
├── django_cool_paginator
├── __init__.py
├── exceptions
│ ├── __init__.py
│ └── tag_exceptions.py
├── templates
│ └── __paginator.html
└── templatetags
│ ├── __init__.py
│ ├── cool_paginate.py
│ └── paginator_tags.py
├── requirements.txt
├── runtests.py
├── setup.py
└── tests
├── __init__.py
├── test-requirements.txt
├── test_settings.py
└── tests.py
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | source=
3 | django_cool_paginator/
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
106 | .idea/
107 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 |
3 | python:
4 | - "3.6"
5 | - "3.5"
6 | - "3.4"
7 |
8 | env:
9 | - DJANGO_VERSION=2.0.0
10 | - DJANGO_VERSION=1.11.0
11 | - DJANGO_VERSION=1.10.0
12 |
13 | install:
14 | - pip install Django==$DJANGO_VERSION --quiet
15 | - pip install -r tests/test-requirements.txt
16 |
17 | before_script:
18 | - flake8 --ignore=E501
19 |
20 | script:
21 | - coverage run runtests.py
22 | - python setup.py build
23 |
24 | after_success:
25 | - coveralls
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jabrail Lezgintsev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include README.md
3 | recursive-include django_cool_paginator/templates *
4 |
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # django-cool-pagination
2 |
3 | [](https://travis-ci.org/joe513/django-cool-pagination)
4 | [](https://coveralls.io/github/joe513/django-cool-pagination?branch=master)
5 | [](https://badge.fury.io/py/django-cool-pagination)
6 |
7 | *django-cool-pagination* is simple pagination app that saves your time.
8 |
9 |
10 |
11 | 
12 |
13 |
14 | ## Prerequisites
15 | Currently it supports Bootstrap 4.x only. So that you have to add [Bootstrap 4](https://getbootstrap.com/docs/4.1/getting-started/download) to your project.
16 |
17 | ## Features
18 |
19 | - _Dynamic query string creation_
20 | - _Length auto control_
21 | - _Fully customizable_ (aspiring)
22 |
23 | ## Installation
24 | ### Installing
25 | #### pip
26 | pip install django-cool-pagination
27 | #### setup.py
28 | git clone https://github.com/joe513/django-cool-pagination.git
29 | cd django-cool-pagination
30 | python setup.py install
31 | ### Setting up
32 | #### Add to `INSTALLED_APPS`
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 |
41 | 'django_cool_paginator'
42 | #### Make sure `request` is in `context_processors`
43 | 'context_processors': [
44 | 'django.template.context_processors.debug',
45 | 'django.template.context_processors.request',
46 | 'django.contrib.auth.context_processors.auth',
47 | 'django.contrib.messages.context_processors.messages',
48 |
49 | ## Using
50 |
51 | ### View
52 | #### FBV (Function based view)
53 |
54 | def listing(request):
55 | contact_list = Contact.objects.all()
56 | paginator = Paginator(contact_list, 25)
57 |
58 | page = request.GET.get('page')
59 | page_obj = paginator.get_page(page)
60 | return render(request, 'list.html', {'page_obj': page_obj})
61 |
62 | #### CBV (Class based view)
63 |
64 | class Listing(ListView):
65 | model = Item
66 | paginate_by = 5
67 |
68 | ### Template
69 | {% load cool_paginate %}
70 |
71 | {% for contact in page_obj %}
72 | ...
73 | {% endfor %}
74 |
75 | {% cool_paginate page_obj=ENTER HERE YOUR PAGE OBJECT! %}
76 |
77 | > **Note:**
78 | You don't have to specify `page` if its name is `page_obj` as default.
79 |
80 | ## Customization
81 | You can customize it so that it works as you want. Customize it by defining settings either in setting.py or
82 | inside of `{% cool_paginate %} `
83 |
84 | #### setting.py
85 |
86 | `COOL_PAGINATOR_NEXT_NAME` - Name for "next" button in pagination bar.
87 | `COOL_PAGINATOR_PREVIOUS_NAME` - Name for "previous" button in pagination bar
88 | `COOL_PAGINATOR_SIZE` - Size of pagination bar (choose: "LARGE" or "SMALL")
89 | `COOL_PAGINATOR_ELASTIC` - What page width is elastic mode enabled from?
90 |
91 | #### {% cool_paginate page_obj next_name previous_name size elastic %}
92 | `page_obj` - Type here your page object.
93 | `next_name` - Name for "next" button in pagination bar.
94 | `previous_name` - Name for "previous" button in pagination bar
95 | `size` - Size of pagination bar (choose: "LARGE" or "SMALL")
96 | `elastic` - What page width is elastic mode enabled from?
97 |
98 | > **Note:**
99 | > `{% cool_paginate %}` has a priority, _django-cool-pagination_ will firstly look at this, after at setting.py
100 |
101 | ## License
102 | This project is licensed under the MIT License - see the LICENSE file for details
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/django_cool_paginator/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Jabrail Lezgintsev'
2 | __credits__ = ['Jabrail Lezgintsev']
3 | __license__ = 'MIT'
4 | __version__ = '0.3.0'
5 | __maintainer__ = 'Jabrail Lezgintsev'
6 | __email__ = 'lezgintsev13@yandex.ru'
7 | __status__ = 'Beta'
8 |
--------------------------------------------------------------------------------
/django_cool_paginator/exceptions/__init__.py:
--------------------------------------------------------------------------------
1 | from .tag_exceptions import PageNotSpecified, RequestNotExists # NOQA
2 |
--------------------------------------------------------------------------------
/django_cool_paginator/exceptions/tag_exceptions.py:
--------------------------------------------------------------------------------
1 | """
2 | These exceptions relate to django-cool-pagination.
3 |
4 | Items:
5 | Exceptions:
6 | - PageNotSpecified(*args, **kwargs)
7 | - RequestNotExists(*args, **kwargs)
8 |
9 | Description:
10 | Exception Description:
11 |
12 | PageNotSpecified:
13 | Raises in case if page wasn't specified at all
14 |
15 | RequestNotExists:
16 | Raises in case if user has forgotten to include request context processor
17 |
18 | """
19 |
20 |
21 | class PageNotSpecified(Exception):
22 | """Raised if page wasn't specified at all"""
23 | pass
24 |
25 |
26 | class RequestNotExists(Exception):
27 | """Raised if user has forgotten to include request context processor"""
28 | pass
29 |
--------------------------------------------------------------------------------
/django_cool_paginator/templates/__paginator.html:
--------------------------------------------------------------------------------
1 | {% load paginator_tags %}
2 |
3 |
52 |
--------------------------------------------------------------------------------
/django_cool_paginator/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joe513/django-cool-pagination/9a803a0fb1b9b141d5b4147e77d8e985484c9b1c/django_cool_paginator/templatetags/__init__.py
--------------------------------------------------------------------------------
/django_cool_paginator/templatetags/cool_paginate.py:
--------------------------------------------------------------------------------
1 | """
2 | Main module for pagination purpose
3 |
4 | This module is designed as main. To load it to your template just write:
5 |
6 | {% load cool_paginate %}
7 |
8 | Items:
9 | Functions:
10 |
11 | - cool_paginate(context, **kwargs)
12 |
13 | Description:
14 | Function description:
15 |
16 | cool_paginate:
17 | Main function for pagination process.
18 |
19 | """
20 |
21 | from django import template
22 | from django.conf import settings
23 |
24 | from django_cool_paginator.exceptions import PageNotSpecified, RequestNotExists
25 |
26 | # TODO Discuss which name is better for the module cool_paginate or cool_pagination
27 |
28 | register = template.Library()
29 |
30 |
31 | @register.inclusion_tag('__paginator.html', takes_context=True)
32 | def cool_paginate(context, **kwargs) -> dict:
33 | """Main function for pagination process."""
34 |
35 | names = (
36 | 'size',
37 | 'next_name',
38 | 'previous_name',
39 | 'elastic',
40 | 'page_obj',
41 | )
42 |
43 | return_dict = {name: value for name, value in zip(names, map(kwargs.get, names))}
44 |
45 | if context.get('request'):
46 | return_dict['request'] = context['request']
47 | else:
48 | raise RequestNotExists(
49 | 'Unable to find request in your template context,'
50 | 'please make sure that you have the request context processor enabled'
51 | )
52 |
53 | if not return_dict.get('page_obj'):
54 | if context.get('page_obj'):
55 | return_dict['page_obj'] = context['page_obj']
56 | else:
57 | raise PageNotSpecified(
58 | 'You customized paginator standard name, '
59 | "but haven't specified it in {% cool_paginate %} tag."
60 | )
61 |
62 | if not return_dict.get('elastic'):
63 | return_dict['elastic'] = getattr(settings, 'COOL_PAGINATOR_ELASTIC', 10)
64 |
65 | return return_dict
66 |
--------------------------------------------------------------------------------
/django_cool_paginator/templatetags/paginator_tags.py:
--------------------------------------------------------------------------------
1 | """
2 | Tags for pagination template which is in templates directory
3 |
4 | These are internal pagination custom tag functions that are needed by paginator template (__paginator.html)
5 | which is in templates directory. User doesn't have to interact with them. They are designed as internal.
6 |
7 | Most of them depend on project settings.
8 |
9 | Items:
10 | Vars:
11 | - COOL_PAGINATOR_NEXT_NAME
12 | - COOL_PAGINATOR_PREVIOUS_NAME
13 | - COOL_PAGINATOR_SIZE
14 |
15 | Functions:
16 | - url_replace(context, field, value)
17 | - ellipsis_or_number(context, paginator, current_page)
18 | - size(chosen_size=None)
19 | - next_name(name=None)
20 | - previous_name(name=None)
21 |
22 | Description:
23 | Function description:
24 |
25 | url_replace:
26 | To avoid GET params loosing
27 | ellipsis_or_number:
28 | To avoid display a long page table
29 | size:
30 | Points to pagination table size.
31 |
32 | """
33 |
34 | from django import template
35 | from django.conf import settings
36 |
37 | register = template.Library()
38 |
39 |
40 | # Pagination settings
41 |
42 | COOL_PAGINATOR_NEXT_NAME = getattr(settings, 'COOL_PAGINATOR_NEXT_NAME', 'Next')
43 | COOL_PAGINATOR_PREVIOUS_NAME = getattr(settings, 'COOL_PAGINATOR_PREVIOUS_NAME', 'Previous')
44 | COOL_PAGINATOR_SIZE = getattr(settings, 'COOL_PAGINATOR_SIZE', None)
45 |
46 | # Tags...
47 |
48 |
49 | # next_name tag
50 | next_name = register.simple_tag(name='next_name', func=lambda name=None: name or COOL_PAGINATOR_NEXT_NAME)
51 |
52 | # previous_name tag
53 | previous_name = register.simple_tag(name='previous_name', func=lambda name=None: name or COOL_PAGINATOR_PREVIOUS_NAME)
54 |
55 |
56 | @register.simple_tag(takes_context=True)
57 | def url_replace(context, field, value):
58 | """
59 | To avoid GET params losing
60 |
61 | :param context: context_obj
62 | :param field: str
63 | :param value: str
64 | :return: dict-like object
65 | """
66 |
67 | query_string = context['request'].GET.copy()
68 | query_string[field] = value
69 |
70 | return query_string.urlencode()
71 |
72 |
73 | # TODO Make this function maximum customizable
74 | @register.simple_tag(takes_context=True)
75 | def ellipsis_or_number(context, paginator, current_page):
76 | """
77 | To avoid display a long pagination bar
78 |
79 | :param context: template context
80 | :param paginator: paginator_obj
81 | :param current_page: int
82 | :return: str or None
83 | """
84 |
85 | # Checks is it first page
86 | chosen_page = int(context['request'].GET['page'] or 1) if 'page' in context['request'].GET else 1
87 |
88 | if current_page in (chosen_page + 1, chosen_page + 2, chosen_page - 1, chosen_page - 2,
89 | paginator.num_pages, paginator.num_pages - 1, 1, 2, chosen_page):
90 | return current_page
91 |
92 | if current_page in (chosen_page + 3, chosen_page - 3):
93 | return '...'
94 |
95 |
96 | @register.simple_tag
97 | def size(chosen_size=None) -> str:
98 | """
99 | Points to pagination bar size.
100 |
101 | :param chosen_size: int
102 | :return: str
103 | """
104 |
105 | return {
106 | 'LARGE': 'pagination-lg',
107 | 'SMALL': 'pagination-sm',
108 | }.get(chosen_size or COOL_PAGINATOR_SIZE, '')
109 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | django
2 |
--------------------------------------------------------------------------------
/runtests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | import sys
5 |
6 | import django
7 |
8 | from django.conf import settings
9 | from django.test.utils import get_runner
10 |
11 |
12 | def run_tests():
13 | os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.test_settings'
14 | django.setup()
15 | test_runner = get_runner(settings)()
16 | failures = test_runner.run_tests(["tests"])
17 | sys.exit(bool(failures))
18 |
19 |
20 | if __name__ == "__main__":
21 | run_tests()
22 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from setuptools import find_packages, setup
4 |
5 | with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme:
6 | README = readme.read()
7 |
8 | os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
9 |
10 | setup(
11 | name='django-cool-pagination',
12 | version='0.3.0',
13 | packages=find_packages(),
14 | include_package_data=True,
15 | license='MIT',
16 | description='Simple pagination app that saves your time.',
17 | long_description_content_type='text/markdown',
18 | long_description=README,
19 | url='https://github.com/joe513/django-cool-pagination',
20 | author='Jabrail Lezgintsev',
21 | author_email='lezgintsev13@yandex.ru',
22 | keywords='python3 django pagination bootstrap4',
23 | project_urls={
24 | 'Source': 'https://github.com/joe513/django-cool-pagination'
25 | },
26 | python_requires='>=3',
27 | classifiers=[
28 | 'Environment :: Web Environment',
29 | 'Framework :: Django',
30 | 'Framework :: Django :: 2.0',
31 | 'Intended Audience :: Developers',
32 | 'License :: OSI Approved :: MIT License',
33 | 'Operating System :: OS Independent',
34 | 'Programming Language :: Python',
35 | 'Programming Language :: Python :: 3.6',
36 | 'Programming Language :: Python :: 3.5',
37 | 'Programming Language :: Python :: 3.4',
38 | 'Topic :: Internet :: WWW/HTTP',
39 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
40 | ],
41 | )
42 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joe513/django-cool-pagination/9a803a0fb1b9b141d5b4147e77d8e985484c9b1c/tests/__init__.py
--------------------------------------------------------------------------------
/tests/test-requirements.txt:
--------------------------------------------------------------------------------
1 | coverage
2 | coveralls
3 | flake8
4 |
--------------------------------------------------------------------------------
/tests/test_settings.py:
--------------------------------------------------------------------------------
1 | import os.path
2 |
3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
4 |
5 |
6 | SECRET_KEY = 'fake-key'
7 |
8 | INSTALLED_APPS = [
9 | 'django_cool_paginator',
10 |
11 | ]
12 |
13 | TEMPLATES = [
14 | {
15 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
16 | 'APP_DIRS': True,
17 | }
18 | ]
19 |
20 | # For testing purposes.
21 |
22 | COOL_PAGINATOR_SIZE = 'SMALL'
23 | COOL_PAGINATOR_NEXT_NAME = 'Go'
24 | COOL_PAGINATOR_PREVIOUS_NAME = 'Previous'
25 |
--------------------------------------------------------------------------------
/tests/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import SimpleTestCase
2 | from django.http import HttpRequest
3 | from django.template import Template, Context
4 | from django.core.paginator import Paginator
5 |
6 | from django_cool_paginator.templatetags import paginator_tags
7 | from django_cool_paginator.exceptions import PageNotSpecified, RequestNotExists
8 |
9 |
10 | class BaseTest(SimpleTestCase):
11 |
12 | def setUp(self):
13 | paginator = Paginator([... for _ in range(30)], 5)
14 | self.page = paginator.page(4)
15 | self.request = HttpRequest()
16 |
17 | self.base_context = {
18 | 'request': self.request,
19 | 'page_obj': paginator.page(4),
20 | }
21 |
22 | self.size_conf = {
23 | 'LARGE': 'pagination-lg',
24 | 'SMALL': 'pagination-sm'
25 | }
26 |
27 |
28 | class PaginatorTagTest(BaseTest):
29 | """These tests are designed for paginator_tags.py internal module which is in templatetags"""
30 |
31 | load = '{% load paginator_tags %}'
32 |
33 | def test_ellipsis_or_number(self):
34 | template_string = Template(self.load + '{% ellipsis_or_number page_obj.paginator page_numb %}')
35 |
36 | self.request.GET['page'] = 5
37 |
38 | context = self.base_context.copy()
39 | context['page_numb'] = 5
40 |
41 | template = template_string.render(Context(context))
42 | self.assertEqual(int(template), 5)
43 |
44 | context['page_numb'] = 8
45 |
46 | template = template_string.render(Context(context))
47 | self.assertEqual(template, '...')
48 |
49 | self.request.GET['page'] = 1
50 | context['page_numb'] = 7
51 |
52 | template = template_string.render(Context(context))
53 | self.assertEqual(template, str(None))
54 |
55 | def test_url_replace(self):
56 | template_string = Template(self.load + "{% url_replace 'page' number %}")
57 |
58 | context = self.base_context.copy()
59 | context['number'] = 2
60 |
61 | template = template_string.render(Context(context))
62 | self.assertEquals(template, 'page=2')
63 |
64 | def test_size(self):
65 | template_string = Template(self.load + '{% size size %}')
66 |
67 | context = {'size': 'LARGE'}
68 |
69 | template = template_string.render(Context(context))
70 | self.assertEqual(template, self.size_conf[context['size']])
71 |
72 | # By default
73 | template = template_string.render(Context())
74 | self.assertEqual(template, self.size_conf[paginator_tags.COOL_PAGINATOR_SIZE])
75 |
76 | def test_previous_name(self):
77 | template_string = Template(self.load + "{% previous_name name=previous_name %}")
78 |
79 | previous_name = 'Bobby'
80 |
81 | template = template_string.render(Context({'previous_name': previous_name}))
82 | self.assertEqual(template, previous_name)
83 |
84 | # By default
85 | template = template_string.render(Context())
86 | self.assertEqual(template, paginator_tags.COOL_PAGINATOR_PREVIOUS_NAME)
87 |
88 | def test_next_name(self):
89 | template_string = Template(self.load + "{% next_name name=next_name %}")
90 |
91 | next_name = 'Jack'
92 |
93 | template = template_string.render(Context({'next_name': next_name}))
94 | self.assertEqual(template, next_name)
95 |
96 | # By default
97 | template = template_string.render(Context({}))
98 | self.assertEqual(template, paginator_tags.COOL_PAGINATOR_NEXT_NAME)
99 |
100 |
101 | class CoolPaginateTest(BaseTest):
102 | """These tests are designed for cool_paginate function which is in cool_paginate.py module"""
103 |
104 | load = '{% load cool_paginate %}'
105 |
106 | def test_page(self):
107 | template_string = Template(self.load + '{% cool_paginate %}')
108 | self.assertTrue(template_string.render(Context(self.base_context.copy())))
109 |
110 | def test_exception(self):
111 | template_string = Template(self.load + '{% cool_paginate %}')
112 |
113 | with self.assertRaisesMessage(RequestNotExists,
114 | 'Unable to find request in your template context,'
115 | 'please make sure that you have the request context processor enabled'
116 | ):
117 | template_string.render(Context())
118 |
119 | with self.assertRaisesMessage(PageNotSpecified,
120 | 'You customized paginator standard name, '
121 | "but haven't specified it in {% cool_paginate %} tag."
122 | ):
123 | template_string.render(Context({'request': self.request}))
124 |
125 | def test_size(self):
126 |
127 | context = self.base_context.copy()
128 | context['size'] = 'LARGE'
129 |
130 | template_string = Template(self.load + '{% cool_paginate size=size %}')
131 | template = template_string.render(Context(context))
132 |
133 | self.assertIn(self.size_conf[context['size']], template)
134 |
135 | # By default
136 | context.pop('size')
137 | template = template_string.render(Context(context))
138 |
139 | self.assertIn(self.size_conf[paginator_tags.COOL_PAGINATOR_SIZE], template)
140 |
141 | def test_next_name(self):
142 |
143 | context = self.base_context.copy()
144 | context['next_name'] = 'Go to'
145 |
146 | template_string = Template(self.load + '{% cool_paginate next_name=next_name %}')
147 | template = template_string.render(Context(context))
148 |
149 | self.assertIn(context['next_name'], template)
150 |
151 | # By default
152 | context.pop('next_name')
153 | template = template_string.render(Context(context))
154 | self.assertIn(paginator_tags.COOL_PAGINATOR_NEXT_NAME, template)
155 |
156 | def test_previous_name(self):
157 |
158 | context = self.base_context.copy()
159 | context['previous_name'] = 'Back to'
160 |
161 | template_string = Template(self.load + '{% cool_paginate previous_name=previous_name %}')
162 | template = template_string.render(Context(context))
163 |
164 | self.assertIn(context['previous_name'], template)
165 |
166 | # By default
167 | context.pop('previous_name')
168 | template = template_string.render(Context(context))
169 | self.assertIn(paginator_tags.COOL_PAGINATOR_PREVIOUS_NAME, template)
170 |
171 | def test_elastic(self):
172 |
173 | context = self.base_context.copy()
174 | context['elastic'] = 5
175 |
176 | standard_template = Template(self.load + '{% cool_paginate elastic=elastic%}').render(Context(context)).strip()
177 |
178 | context['elastic'] = 10
179 | template = Template(self.load + '{% cool_paginate elastic=elastic%}').render(Context(context)).strip()
180 |
181 | self.assertHTMLNotEqual(template, standard_template)
182 |
--------------------------------------------------------------------------------