# Bootstrap django-datetime-widget is a simple and clean widget for DateField, # Timefiled and DateTimeField in Django framework. It is based on Bootstrap # datetime picker, supports Bootstrap 2 # # https://github.com/asaglimbeni/django-datetime-widget # # License: BSD # Initial Author: Alfredo Saglimbeni import json import re import uuid from django.forms.widgets import DateTimeInput, TimeInput, SelectMultiple from django.utils.formats import get_language from django.utils.safestring import mark_safe DATE_FORMAT_JS_PY_MAPPING = { 'P': '%p', 'ss': '%S', 'ii': '%M', 'hh': '%H', 'HH': '%I', 'dd': '%d', 'mm': '%m', 'yy': '%y', 'yyyy': '%Y', } DATE_FORMAT_TO_PYTHON_REGEX = re.compile(r'\b(' + '|'.join(DATE_FORMAT_JS_PY_MAPPING.keys()) + r')\b') DATE_FORMAT_PY_JS_MAPPING = { '%M': 'ii', '%m': 'mm', '%I': 'HH', '%H': 'hh', '%d': 'dd', '%Y': 'yyyy', '%y': 'yy', '%p': 'P', '%S': 'ss' } DATE_FORMAT_TO_JS_REGEX = re.compile(r'(? %(rendered_widget)s %(clear_button)s """ CLEAR_BTN_TEMPLATE = """""" class PickerWidgetMixin(object): format_name = None glyphicon = None def __init__(self, attrs=None, options=None, usel10n=None): if attrs is None: attrs = {'readonly': ''} self.options = options if get_language(): self.options['language'] = get_language().split('-')[0] # We're not doing localisation, get the Javascript date format provided by the user, # with a default, and convert it to a Python data format for later string parsing date_format = self.options['format'] self.format = DATE_FORMAT_TO_PYTHON_REGEX.sub( lambda x: DATE_FORMAT_JS_PY_MAPPING[x.group()], date_format ) super(PickerWidgetMixin, self).__init__(attrs, format=self.format) def render(self, name, value, attrs=None): final_attrs = self.build_attrs(attrs) rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs) #if not set, autoclose have to be true. self.options.setdefault('autoclose', True) # Build javascript options out of python dictionary options_list = [] for key, value in iter(self.options.items()): options_list.append("%s: %s" % (key, json.dumps(value))) js_options = ",\n".join(options_list) # Use provided id or generate hex to avoid collisions in document id = final_attrs.get('id', uuid.uuid4().hex) return mark_safe(BOOTSTRAP_INPUT_TEMPLATE % dict( id=id, rendered_widget=rendered_widget, clear_button=CLEAR_BTN_TEMPLATE if self.options.get('clearBtn') else '', glyphicon=self.glyphicon, options=js_options ) ) class DateTimeWidget(PickerWidgetMixin, DateTimeInput): """ DateTimeWidget is the corresponding widget for Datetime field, it renders both the date and time sections of the datetime picker. """ format_name = 'DATETIME_INPUT_FORMATS' glyphicon = 'glyphicon-th' def __init__(self, attrs=None, options=None, usel10n=None): if options is None: options = {} # Set the default options to show only the datepicker object options['format'] = options.get('format', 'dd/mm/yyyy hh:ii') super(DateTimeWidget, self).__init__(attrs, options, usel10n) class TimeWidget(TimeInput): """ TimeWidget is a widget for time selection, it uses the HTML5 "time" input type and has a bit of a fallback mechanism with the presence of the pattern attribute in case a standard text input is used. """ input_type = 'time' def __init__(self, **kwargs): super(TimeWidget, self).__init__(**kwargs) self.attrs['step'] = '300' # 5 minutes self.attrs['pattern'] = '[0-9]{2}:[0-9]{2}' class WeekdaysWidget(SelectMultiple): def render(self, name, value, attrs=None, choices=()): s = [] value = value or [] for choice_id, choice_label in self.choices: s.append('
  • ' % { 'name': name, 'checked': 'checked' if choice_id in value else '', 'choice_id': choice_id, 'choice_label': choice_label}) return mark_safe('') def value_from_datadict(self, data, files, name): choices = [] for choice_id, choice_label in self.choices: if data.get('%s-%s' % (name, choice_id)): choices.append(choice_id) return choices