Project

General

Profile

Download (5.21 KB) Statistics
| Branch: | Tag: | Revision:

root / corbo / widgets.py @ 6c7e99a0

1
# Bootstrap django-datetime-widget is a simple and clean widget for DateField,
2
# Timefiled and DateTimeField in Django framework. It is based on Bootstrap
3
# datetime picker, supports Bootstrap 2
4
#
5
# https://github.com/asaglimbeni/django-datetime-widget
6
#
7
# License: BSD
8
# Initial Author: Alfredo Saglimbeni
9

    
10
import json
11
import re
12
import uuid
13

    
14
from django.forms.widgets import DateTimeInput, DateInput, TimeInput
15
from django.utils.formats import get_language
16
from django.utils.safestring import mark_safe
17

    
18
DATE_FORMAT_JS_PY_MAPPING = {
19
    'P': '%p',
20
    'ss': '%S',
21
    'ii': '%M',
22
    'hh': '%H',
23
    'HH': '%I',
24
    'dd': '%d',
25
    'mm': '%m',
26
    'yy': '%y',
27
    'yyyy': '%Y',
28
}
29

    
30
DATE_FORMAT_TO_PYTHON_REGEX = re.compile(r'\b(' + '|'.join(DATE_FORMAT_JS_PY_MAPPING.keys()) + r')\b')
31

    
32

    
33
DATE_FORMAT_PY_JS_MAPPING = {
34
    '%M': 'ii',
35
    '%m': 'mm',
36
    '%I': 'HH',
37
    '%H': 'hh',
38
    '%d': 'dd',
39
    '%Y': 'yyyy',
40
    '%y': 'yy',
41
    '%p': 'P',
42
    '%S': 'ss'
43
}
44

    
45
DATE_FORMAT_TO_JS_REGEX = re.compile(r'(?<!\w)(' + '|'.join(DATE_FORMAT_PY_JS_MAPPING.keys()) + r')\b')
46

    
47

    
48
BOOTSTRAP_INPUT_TEMPLATE = """
49
       <div id="%(id)s"  class="controls input-append date">
50
           %(rendered_widget)s
51
           %(clear_button)s
52
           <span class="add-on"><i class="icon-th"></i></span>
53
       </div>
54
       <script type="text/javascript">
55
           $("#%(id)s").datetimepicker({%(options)s});
56
       </script>
57
       """
58

    
59
CLEAR_BTN_TEMPLATE = """<span class="add-on"><i class="icon-remove"></i></span>"""
60

    
61

    
62
class PickerWidgetMixin(object):
63

    
64
    format_name = None
65
    glyphicon = None
66

    
67
    def __init__(self, attrs=None, options=None, usel10n=None):
68

    
69
        if attrs is None:
70
            attrs = {'readonly': ''}
71

    
72
        self.options = options
73
        self.options['language'] = get_language().split('-')[0]
74

    
75
        # We're not doing localisation, get the Javascript date format provided by the user,
76
        # with a default, and convert it to a Python data format for later string parsing
77
        date_format = self.options['format']
78
        self.format = DATE_FORMAT_TO_PYTHON_REGEX.sub(
79
            lambda x: DATE_FORMAT_JS_PY_MAPPING[x.group()],
80
            date_format
81
            )
82

    
83
        super(PickerWidgetMixin, self).__init__(attrs, format=self.format)
84

    
85
    def render(self, name, value, attrs=None):
86
        final_attrs = self.build_attrs(attrs)
87
        rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs)
88

    
89
        #if not set, autoclose have to be true.
90
        self.options.setdefault('autoclose', True)
91

    
92
        # Build javascript options out of python dictionary
93
        options_list = []
94
        for key, value in iter(self.options.items()):
95
            options_list.append("%s: %s" % (key, json.dumps(value)))
96

    
97
        js_options = ",\n".join(options_list)
98

    
99
        # Use provided id or generate hex to avoid collisions in document
100
        id = final_attrs.get('id', uuid.uuid4().hex)
101

    
102
        return mark_safe(BOOTSTRAP_INPUT_TEMPLATE % dict(
103
                    id=id,
104
                    rendered_widget=rendered_widget,
105
                    clear_button=CLEAR_BTN_TEMPLATE if self.options.get('clearBtn') else '',
106
                    glyphicon=self.glyphicon,
107
                    options=js_options
108
                    )
109
        )
110

    
111

    
112
class DateTimeWidget(PickerWidgetMixin, DateTimeInput):
113
    """
114
    DateTimeWidget is the corresponding widget for Datetime field, it renders both the date and time
115
    sections of the datetime picker.
116
    """
117

    
118
    format_name = 'DATETIME_INPUT_FORMATS'
119
    glyphicon = 'glyphicon-th'
120

    
121
    def __init__(self, attrs=None, options=None, usel10n=None):
122

    
123
        if options is None:
124
            options = {}
125

    
126
        # Set the default options to show only the datepicker object
127
        options['format'] = options.get('format', 'dd/mm/yyyy hh:ii')
128

    
129
        super(DateTimeWidget, self).__init__(attrs, options, usel10n)
130

    
131

    
132
class DateWidget(PickerWidgetMixin, DateInput):
133
    """
134
    DateWidget is the corresponding widget for Date field, it renders only the date section of
135
    datetime picker.
136
    """
137

    
138
    format_name = 'DATE_INPUT_FORMATS'
139
    glyphicon = 'glyphicon-calendar'
140

    
141
    def __init__(self, attrs=None, options=None, usel10n=None):
142

    
143
        if options is None:
144
            options = {}
145

    
146
        # Set the default options to show only the datepicker object
147
        options['startView'] = options.get('startView', 2)
148
        options['minView'] = options.get('minView', 2)
149
        options['format'] = options.get('format', 'dd/mm/yyyy')
150

    
151
        super(DateWidget, self).__init__(attrs, options, usel10n)
152

    
153

    
154
class TimeWidget(PickerWidgetMixin, TimeInput):
155
    """
156
    TimeWidget is the corresponding widget for Time field, it renders only the time section of
157
    datetime picker.
158
    """
159

    
160
    format_name = 'TIME_INPUT_FORMATS'
161
    glyphicon = 'glyphicon-time'
162

    
163
    def __init__(self, attrs=None, options=None, usel10n=None):
164

    
165
        if options is None:
166
            options = {}
167

    
168
        # Set the default options to show only the timepicker object
169
        options['startView'] = options.get('startView', 1)
170
        options['minView'] = options.get('minView', 0)
171
        options['maxView'] = options.get('maxView', 1)
172
        options['format'] = options.get('format', 'hh:ii')
173

    
174
        super(TimeWidget, self).__init__(attrs, options, usel10n)
(12-12/13)