Completed
Push — master ( efcb62...4ad93c )
by Asif
01:01
created

crud_detail()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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