Completed
Push — master ( 9b088f...73be1b )
by Asif
01:05
created

get_pagination_context()   F

Complexity

Conditions 21

Size

Total Lines 83

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 83
rs 2.1114
cc 21

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like get_pagination_context() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import re
2
from math import floor
3
from django import template
4
from itertools import chain
5
from django.template.defaultfilters import stringfilter
6
from collections import namedtuple
7
8
try:
9
    from django.utils.encoding import force_text
10
except ImportError:
11
    from django.utils.encoding import force_unicode as force_text
12
13
register = template.Library()
14
Field = namedtuple('Field', 'name verbose_name')
15
16
17
@register.filter
18
@stringfilter
19
def undertospaced(value):
20
    return value.replace("_", " ").title()
21
22
23
@register.filter
24
def get_value(obj, field):
25
    try:
26
        return getattr(obj, 'get_%s_display' % field)()
27
    except:
28
        return getattr(obj, field)
29
30
31
@register.filter
32
def get_model_fields(obj):
33
    model = obj.__class__
34
    excludes = ['pk']
35
36
    property_fields = []
37
    for name in dir(model):
38
        if name not in excludes and isinstance(
39
            getattr(model, name, None), property
40
        ):
41
            property_fields.append(Field(name=name, verbose_name=name))
42
43
    return chain(obj._meta.fields, property_fields)
44
45
46
@register.filter
47
def get_verbose_field_name(instance, field_name):
48
    """
49
    Returns verbose_name for a field.
50
    """
51
    return instance._meta.get_field(field_name).verbose_name.title()
52
53
54
@register.filter(is_safe=True)
55
def label_with_class(value, arg):
56
    """Style adjustments"""
57
    return value.label_tag(attrs={'class': arg})
58
59
60
@register.filter(is_safe=True)
61
def input_with_class(value, arg):
62
    value.field.widget.attrs['class'] = arg
63
    return value
64
65
66
@register.filter(is_safe=True)
67
def inline_objects(object, inline_fk):
68
    inline_model = inline_fk.model
69
    related_filter = inline_fk.get_forward_related_filter(object)
70
    return inline_model.objects.filter(**related_filter)
71
72
73
@register.inclusion_tag('widgets/tables/pagination.html')
74
def bootstrap_pagination(page, **kwargs):
75
    pagination_kwargs = kwargs.copy()
76
    pagination_kwargs['page'] = page
77
    return get_pagination_context(**pagination_kwargs)
78
79
80
def get_pagination_context(page, pages_to_show=11,
81
                           url=None, size=None, extra=None,
82
                           parameter_name='page'):
83
    """
84
    Generate Bootstrap pagination context from a page object
85
    """
86
    pages_to_show = int(pages_to_show)
87
    if pages_to_show < 1:
88
        raise ValueError(
89
            "Pagination pages_to_show should be a positive"
90
            "integer, you specified {pages}".format(
91
                pages=pages_to_show)
92
        )
93
    num_pages = page.paginator.num_pages
94
    current_page = page.number
95
    half_page_num = int(floor(pages_to_show / 2))
96
    if half_page_num < 0:
97
        half_page_num = 0
98
    first_page = current_page - half_page_num
99
    if first_page <= 1:
100
        first_page = 1
101
    if first_page > 1:
102
        pages_back = first_page - half_page_num
103
        if pages_back < 1:
104
            pages_back = 1
105
    else:
106
        pages_back = None
107
    last_page = first_page + pages_to_show - 1
108
    if pages_back is None:
109
        last_page += 1
110
    if last_page > num_pages:
111
        last_page = num_pages
112
    if last_page < num_pages:
113
        pages_forward = last_page + half_page_num
114
        if pages_forward > num_pages:
115
            pages_forward = num_pages
116
    else:
117
        pages_forward = None
118
        if first_page > 1:
119
            first_page -= 1
120
        if pages_back is not None and pages_back > 1:
121
            pages_back -= 1
122
        else:
123
            pages_back = None
124
    pages_shown = []
125
    for i in range(first_page, last_page + 1):
126
        pages_shown.append(i)
127
        # Append proper character to url
128
    if url:
129
        # Remove existing page GET parameters
130
        url = force_text(url)
131
        url = re.sub(r'\?{0}\=[^\&]+'.format(parameter_name), '?', url)
132
        url = re.sub(r'\&{0}\=[^\&]+'.format(parameter_name), '', url)
133
        # Append proper separator
134
        if '?' in url:
135
            url += '&'
136
        else:
137
            url += '?'
138
            # Append extra string to url
139
    if extra:
140
        if not url:
141
            url = '?'
142
        url += force_text(extra) + '&'
143
    if url:
144
        url = url.replace('?&', '?')
145
    # Set CSS classes, see http://getbootstrap.com/components/#pagination
146
    pagination_css_classes = ['pagination']
147
    if size == 'small':
148
        pagination_css_classes.append('pagination-sm')
149
    elif size == 'large':
150
        pagination_css_classes.append('pagination-lg')
151
        # Build context object
152
    return {
153
        'bootstrap_pagination_url': url,
154
        'num_pages': num_pages,
155
        'current_page': current_page,
156
        'first_page': first_page,
157
        'last_page': last_page,
158
        'pages_shown': pages_shown,
159
        'pages_back': pages_back,
160
        'pages_forward': pages_forward,
161
        'pagination_css_classes': ' '.join(pagination_css_classes),
162
        'parameter_name': parameter_name,
163
    }
164