Completed
Push — master ( c965ec...1673fb )
by Asif
10s
created

get_model_fields()   B

Complexity

Conditions 6

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 6
c 4
b 0
f 0
dl 0
loc 13
rs 8
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, exclude=[]):
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
    ret = chain(obj._meta.fields, property_fields)
43
    return [i for i in ret if i.name not in exclude]
44
45
46
@register.filter
47
def get_verbose_field_name(instance, field_name):
48
    """
49
    Returns verbose_name for a field.
50
    """
51
    fields = [field.name for field in instance._meta.fields]
52
    if field_name in fields:
53
        return instance._meta.get_field(field_name).verbose_name.title()
54
    else:
55
        return field_name.title()
56
57
58
@register.filter(is_safe=True)
59
def label_with_class(value, arg):
60
    """Style adjustments"""
61
    return value.label_tag(attrs={'class': arg})
62
63
64
@register.filter(is_safe=True)
65
def input_with_class(value, arg):
66
    value.field.widget.attrs['class'] = arg
67
    return value
68
69
70
@register.filter(is_safe=True)
71
def inline_objects(object, inline_fk):
72
    inline_model = inline_fk.model
73
    related_filter = {inline_fk.name: object}
74
    return inline_model.objects.filter(**related_filter)
75
76
77
@register.inclusion_tag('widgets/tables/pagination.html')
78
def bootstrap_pagination(page, **kwargs):
79
    pagination_kwargs = kwargs.copy()
80
    pagination_kwargs['page'] = page
81
    return get_pagination_context(**pagination_kwargs)
82
83
84
def get_pagination_context(page, pages_to_show=11,
85
                           url=None, size=None, extra=None,
86
                           parameter_name='page'):
87
    """
88
    Generate Bootstrap pagination context from a page object
89
    """
90
    pages_to_show = int(pages_to_show)
91
    if pages_to_show < 1:
92
        raise ValueError(
93
            "Pagination pages_to_show should be a positive"
94
            "integer, you specified {pages}".format(
95
                pages=pages_to_show)
96
        )
97
    num_pages = page.paginator.num_pages
98
    current_page = page.number
99
    half_page_num = int(floor(pages_to_show / 2))
100
    if half_page_num < 0:
101
        half_page_num = 0
102
    first_page = current_page - half_page_num
103
    if first_page <= 1:
104
        first_page = 1
105
    if first_page > 1:
106
        pages_back = first_page - half_page_num
107
        if pages_back < 1:
108
            pages_back = 1
109
    else:
110
        pages_back = None
111
    last_page = first_page + pages_to_show - 1
112
    if pages_back is None:
113
        last_page += 1
114
    if last_page > num_pages:
115
        last_page = num_pages
116
    if last_page < num_pages:
117
        pages_forward = last_page + half_page_num
118
        if pages_forward > num_pages:
119
            pages_forward = num_pages
120
    else:
121
        pages_forward = None
122
        if first_page > 1:
123
            first_page -= 1
124
        if pages_back is not None and pages_back > 1:
125
            pages_back -= 1
126
        else:
127
            pages_back = None
128
    pages_shown = []
129
    for i in range(first_page, last_page + 1):
130
        pages_shown.append(i)
131
        # Append proper character to url
132
    if url:
133
        # Remove existing page GET parameters
134
        url = force_text(url)
135
        url = re.sub(r'\?{0}\=[^\&]+'.format(parameter_name), '?', url)
136
        url = re.sub(r'\&{0}\=[^\&]+'.format(parameter_name), '', url)
137
        # Append proper separator
138
        if '?' in url:
139
            url += '&'
140
        else:
141
            url += '?'
142
            # Append extra string to url
143
    if extra:
144
        if not url:
145
            url = '?'
146
        url += force_text(extra) + '&'
147
    if url:
148
        url = url.replace('?&', '?')
149
    # Set CSS classes, see http://getbootstrap.com/components/#pagination
150
    pagination_css_classes = ['pagination']
151
    if size == 'small':
152
        pagination_css_classes.append('pagination-sm')
153
    elif size == 'large':
154
        pagination_css_classes.append('pagination-lg')
155
        # Build context object
156
    return {
157
        'bootstrap_pagination_url': url,
158
        'num_pages': num_pages,
159
        'current_page': current_page,
160
        'first_page': first_page,
161
        'last_page': last_page,
162
        'pages_shown': pages_shown,
163
        'pages_back': pages_back,
164
        'pages_forward': pages_forward,
165
        'pagination_css_classes': ' '.join(pagination_css_classes),
166
        'parameter_name': parameter_name,
167
    }
168