Login

Datetime widget

Author:
pigletto
Posted:
August 27, 2007
Language:
Python
Version:
.96
Score:
8 (after 8 ratings)

This widget uses: DHTML Calendar Widget. It is very simple implementation but may be easily extended/changed/refined.

  1. Necessary files: First download calendar package and extract it to your MEDIA folder (MEDIA/calendar/...) You'll also need a small gif that will be shown as a button that allows user to display calendar. By default this 'gif' is searched at '[MEDIA]images/calbutton.gif' but you may change this path in the code (calbtn variable). You need to download or create callbutton.gif image by yourself (it is not included).
  2. Include css and js files in your page (as shown in the comment in the code).
  3. In form code assign a widget to a field as usual (see newforms documentation for more details).
  4. It is possible to change date format by specifying different value for 'dformat' attribute of widget class.

If you get javascript errors while trying to open calendar try to use english translation file (calendar-en.js). I've found that some translations, eg. Polish, are broken by default. In this case you should override your language translation with english one and translate it by yourself (it is easy).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# -*- coding: utf-8 -*-
# widgets.py
#
# To use you have to put calendar/ (from http://www.dynarch.com/projects/calendar/)
# to your MEDIA folder and then include such links on your page:
# <!-- calendar -->
# <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}calendar/calendar-win2k-cold-2.css" />
#<script type="text/javascript" src="{{ MEDIA_URL }}calendar/calendar.js"></script>
# <!-- this is translation file - choose your language here -->
#<script type="text/javascript" src="{{ MEDIA_URL }}calendar/lang/calendar-pl.js"></script>
#<script type="text/javascript" src="{{ MEDIA_URL }}calendar/calendar-setup.js"></script>
#<!-- /calendar -->

from django.utils.encoding import force_unicode
from django.conf import settings
from django import forms
import datetime, time
from django.utils.safestring import mark_safe

# DATETIMEWIDGET
calbtn = u"""<img src="%simages/calbutton.gif" alt="calendar" id="%s_btn" style="cursor: pointer; border: 1px solid #8888aa;" title="Select date and time"
            onmouseover="this.style.background='#444444';" onmouseout="this.style.background=''" />
<script type="text/javascript">
    Calendar.setup({
        inputField     :    "%s",
        ifFormat       :    "%s",
        button         :    "%s_btn",
        singleClick    :    true,
        showsTime      :    true
    });
</script>"""

class DateTimeWidget(forms.widgets.TextInput):
    dformat = '%Y-%m-%d %H:%M'
    def render(self, name, value, attrs=None):
        if value is None: value = ''
        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
        if value != '': 
            try:
                final_attrs['value'] = \
                                   force_unicode(value.strftime(self.dformat))
            except:
                final_attrs['value'] = \
                                   force_unicode(value)
        if not final_attrs.has_key('id'):
            final_attrs['id'] = u'%s_id' % (name)
        id = final_attrs['id']
        
        jsdformat = self.dformat #.replace('%', '%%')
        cal = calbtn % (settings.MEDIA_URL, id, id, jsdformat, id)
        a = u'<input%s />%s' % (forms.util.flatatt(final_attrs), cal)
        return mark_safe(a)

    def value_from_datadict(self, data, files, name):
        dtf = forms.fields.DEFAULT_DATETIME_INPUT_FORMATS
        empty_values = forms.fields.EMPTY_VALUES

        value = data.get(name, None)
        if value in empty_values:
            return None
        if isinstance(value, datetime.datetime):
            return value
        if isinstance(value, datetime.date):
            return datetime.datetime(value.year, value.month, value.day)
        for format in dtf:
            try:
                return datetime.datetime(*time.strptime(value, format)[:6])
            except ValueError:
                continue
        return None

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

pigletto (on September 3, 2007):

There was a little bug with unnecessary replacing percent sign in line: jsdformat = self.dformat.replace('%', '%%')

This is fixed now.

#

pigletto (on September 5, 2007):

Method value_from_datadict has been added so now widget returns datetime.datetime objects

#

pigletto (on September 28, 2007):

Small fix applied to line:

final_attrs['value'] = ...

When user entered wrong value, eg: 'qwerty' as a date it was incorrectly handled.

#

tttallis (on January 22, 2008):

I had to change line 17 to:

import datetime, time

to get this to work.

#

pigletto (on February 7, 2008):

Thanks tttallis, I've updated the code

#

tug (on April 11, 2008):

Update import:

import datetime, time

instead of:

from datetime import datetime, time

My version of «value_from_datadict»:

def value_from_datadict(self, data, files, name):
    value = data.get(name, None)
    if value:
        return datetime.date(*time.strptime(value, self.dformat)[:3])

    return None

#

mirobe (on September 10, 2008):

I needed to use mark_safe with output.

#

nicowaisman (on November 21, 2008):

you will need a:

return mark_safe(a)

if you want to be able to print directly, without using as_p

#

josebenjaminp (on January 30, 2013):

The widget is good! but needs some changes, first, in the <script>

<script type="text/javascript">//<![CDATA[

Calendar.setup({
    inputField : "%s",
    dateFormat : "%s",
    trigger    : "%s_btn",
    onSelect   : function() { this.hide() },
    showTime   : 12
});

//]]></script>

second:

this line is deprecated:

dtf = forms.fields.DEFAULT_DATETIME_INPUT_FORMATS

change and import:

from django.utils import formats

...

dtf = formats.get_format("DATETIME_INPUT_FORMATS")[0]

enjoy!

#

Please login first before commenting.