Ticket #6231: ticket_6231_v4.patch
File ticket_6231_v4.patch, 25.1 KB (added by , 16 years ago) |
---|
-
django/forms/extras/widgets.py
6 6 import re 7 7 8 8 from django.forms.widgets import Widget, Select 9 from django.utils.dates import MONTHS 9 from django.utils.dates import MONTHS, MONTHS_AP, MONTHS_3 10 10 from django.utils.safestring import mark_safe 11 from django.conf import settings 11 12 12 __all__ = ('SelectDateWidget', )13 __all__ = ('SelectDateWidget', 'SelectTimeWidget',) 13 14 14 15 RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') 15 16 16 class SelectDateWidget(Widget): 17 18 class SelectDateWidgetBase(Widget): 17 19 """ 20 Base class for SelectDateWidget, SelectDateTimeWidget and 21 SelectTimeWidget. 22 """ 23 def __init__(self, attrs=None, format=None, required=True): 24 if attrs is None: 25 attrs = {} 26 self.attrs = attrs 27 self.values = {} 28 self.format = self.parse_format(format) 29 self.required = required 30 31 def render(self, name, value, attrs=None): 32 """ 33 Return the html code of the widget. 34 """ 35 if 'id' in self.attrs: 36 id_ = self.attrs['id'] 37 else: 38 id_ = 'id_%s' % name 39 local_attrs = self.build_attrs() 40 self.values = self.parse_value(value) 41 output = [] 42 for (n, fmt) in self.format: 43 select_name = '%s_%s' % (name, n) 44 local_attrs['id'] = '%s_%s' % (id_, n) 45 if hasattr(self, '%s_choices' % n): 46 choices=getattr(self, '%s_choices' % n)(fmt) 47 if not self.required or not self.values[n]: 48 choices.insert(0, (-1, '---')) 49 select = Select(choices=choices) 50 html = select.render(select_name, self.values[n], local_attrs) 51 output.append(html) 52 return mark_safe(u'\n'.join(output)) 53 54 def id_for_label(self, id_): 55 return '%s_%s' % (self.format[0][1], id_) 56 id_for_label = classmethod(id_for_label) 57 58 def value_from_datadict(self, data, files, name): 59 raise NotImplementedError('SelectDateWidgetBase::value_from_datadict()\ 60 is abstract and must be implemented in child classes') 61 62 def parse_format(self, fmt): 63 raise NotImplementedError('SelectDateWidgetBase::parse_format() is \ 64 abstract and must be implemented in child classes') 65 66 def parse_value(self, fmt): 67 raise NotImplementedError('SelectDateWidgetBase::parse_value() is \ 68 abstract and must be implemented in child classes') 69 70 71 class SelectDateWidget(SelectDateWidgetBase): 72 """ 18 73 A Widget that splits date input into three <select> boxes. 19 74 20 75 This also serves as an example of a Widget that has more than one HTML 21 76 element and hence implements value_from_datadict. 22 77 """ 23 none_value = (0, '---')24 month_field = '%s_month'25 day_field = '%s_day'26 year_field = '%s_year'27 78 28 def __init__(self, attrs=None, years=None, required=True):79 def __init__(self, attrs=None, years=None, format=None, required=True): 29 80 # years is an optional list/tuple of years to use in the "year" select box. 30 self.attrs = attrs or {}31 self.required = required32 81 if years: 33 82 self.years = years 34 83 else: 35 84 this_year = datetime.date.today().year 36 85 self.years = range(this_year, this_year+10) 86 super(SelectDateWidget, self).__init__(attrs, format, required) 37 87 38 def render(self, name, value, attrs=None): 39 try: 40 year_val, month_val, day_val = value.year, value.month, value.day 41 except AttributeError: 42 year_val = month_val = day_val = None 43 if isinstance(value, basestring): 44 match = RE_DATE.match(value) 45 if match: 46 year_val, month_val, day_val = [int(v) for v in match.groups()] 88 def value_from_datadict(self, data, files, name): 89 vals = [] 90 y = data.get('%s_year' % name) 91 m = data.get('%s_month' % name) 92 d = data.get('%s_day' % name) 93 if y == m == d == '-1': 94 return None 95 if y and m and d: 96 return u'-'.join([y, m, d]) 97 return data.get(name, None) 47 98 48 output = [] 49 50 if 'id' in self.attrs: 51 id_ = self.attrs['id'] 99 def parse_value(self, val): 100 ret = {} 101 if isinstance(val, datetime.date): 102 ret['month'] = val.month 103 ret['day'] = val.day 104 ret['year'] = val.year 52 105 else: 53 id_ = 'id_%s' % name 106 try: 107 l = map(int, val.split('-')) 108 except (ValueError, AttributeError): 109 l = (None, None, None) 110 for i, k in [(0, 'year'), (1, 'month'), (2, 'day')]: 111 try: 112 ret[k] = l[i] 113 except IndexError: 114 ret[k] = None 115 return ret 54 116 55 month_choices = MONTHS.items() 56 if not (self.required and value): 57 month_choices.append(self.none_value) 58 month_choices.sort() 59 local_attrs = self.build_attrs(id=self.month_field % id_) 60 s = Select(choices=month_choices) 61 select_html = s.render(self.month_field % name, month_val, local_attrs) 62 output.append(select_html) 117 def parse_format(self, fmt): 118 """ 119 Parse the given format `fmt` and set the format property. 120 """ 121 if fmt is None: 122 fmt = settings.DATE_FORMAT 123 ret = [] 124 for item in fmt: 125 if item in ['d', 'D', 'j', 'L']: 126 ret.append(('day', item,)) 127 elif item in ['n', 'm', 'F', 'b', 'M', 'N']: 128 ret.append(('month', item,)) 129 elif item in ['y', 'Y']: 130 ret.append(('year', item,)) 131 return ret 63 132 64 day_choices = [(i, i) for i in range(1, 32)] 65 if not (self.required and value): 66 day_choices.insert(0, self.none_value) 67 local_attrs['id'] = self.day_field % id_ 68 s = Select(choices=day_choices) 69 select_html = s.render(self.day_field % name, day_val, local_attrs) 70 output.append(select_html) 133 def month_choices(self, fmt): 134 """ 135 Return list of choices (tuple (key, value)) for monthes select. 136 """ 137 if fmt == 'n': 138 # month numbers without leading 0 (1 .. 12) 139 return [(i, i) for i in range(1, 13)] 140 elif fmt == 'm': 141 # month numbers with leading 0 (01 .. 12) 142 return [(i, '%02d' % i) for i in range(1, 13)] 143 elif fmt in ['F', 'b', 'M', 'N']: 144 if fmt == 'F': 145 # full month names 146 month_choices = MONTHS.items() 147 elif fmt == 'b': 148 # 3 first letters of month lowercase 149 month_choices = [(k, v.lower()) for (k, v) in MONTHS_3.items()] 150 elif fmt == 'M': 151 # 3 first letters of month 152 month_choices = MONTHS_3.items() 153 elif fmt == 'N': 154 # abbrev of month names 155 month_choices = MONTHS_AP.items() 156 month_choices.sort() 157 return month_choices 158 return [] 71 159 72 year_choices = [(i, i) for i in self.years] 73 if not (self.required and value): 74 year_choices.insert(0, self.none_value) 75 local_attrs['id'] = self.year_field % id_ 76 s = Select(choices=year_choices) 77 select_html = s.render(self.year_field % name, year_val, local_attrs) 78 output.append(select_html) 160 def day_choices(self, fmt): 161 """ 162 Return list of choices (tuple (key, value)) for days select. 163 """ 164 if fmt == 'j': 165 # day of month number without leading 0 166 return [(i, i) for i in range(1, 32)] 167 elif fmt == 'd': 168 # day of month number with leading 0 169 return [(i, '%02d' % i) for i in range(1, 32)] 170 return [] 79 171 80 return mark_safe(u'\n'.join(output)) 172 def year_choices(self, fmt): 173 """ 174 Return list of choices (tuple (key, value)) for years select. 175 """ 176 if fmt == 'Y': 177 # years with 4 numbers 178 return [(i, i) for i in self.years] 179 elif fmt == 'y': 180 # years with only the last 2 numbers 181 return [(i, str(i)[-2:]) for i in self.years] 182 return [] 81 183 82 def id_for_label(self, id_):83 return '%s_month' % id_84 id_for_label = classmethod(id_for_label)85 184 185 class SelectTimeWidget(SelectDateWidgetBase): 186 """ 187 A Widget that splits time input into two or three <select> boxes. 188 XXX: at the moment it is limited to theses formats: 'Hi' and 'His'. 189 """ 190 def __init__(self, attrs=None, format=None, required=True): 191 super(SelectTimeWidget, self).__init__(attrs, format, required) 192 193 def parse_format(self, fmt): 194 if fmt not in ['Hi', 'His']: 195 fmt = 'Hi' 196 ret = [] 197 for item in fmt: 198 if item == 'H': 199 ret.append(('hour', item,)) 200 elif item == 'i': 201 ret.append(('minute', item,)) 202 elif item == 's': 203 ret.append(('second', item,)) 204 return ret 205 206 def parse_value(self, val): 207 ret = {} 208 if isinstance(val, datetime.time): 209 ret['hour'] = val.hour 210 ret['minute'] = val.minute 211 ret['second'] = val.second 212 else: 213 try: 214 l = map(int, val.split(':')) 215 except (ValueError, AttributeError): 216 l = (None, None, None) 217 for i, k in [(0, 'hour'), (1, 'minute'), (2, 'second')]: 218 try: 219 ret[k] = l[i] 220 except IndexError: 221 ret[k] = None 222 return ret 223 86 224 def value_from_datadict(self, data, files, name): 87 y = data.get(self.year_field % name) 88 m = data.get(self.month_field % name) 89 d = data.get(self.day_field % name) 90 if y == m == d == "0": 91 return None 92 if y and m and d: 93 return '%s-%s-%s' % (y, m, d) 225 vals = [] 226 h = data.get('%s_hour' % name) 227 m = data.get('%s_minute' % name) 228 s = data.get('%s_second' % name) 229 if h and m: 230 if s: 231 return u':'.join([h, m, s]) 232 else: 233 return u':'.join([h, m]) 94 234 return data.get(name, None) 235 236 def hour_choices(self, fmt): 237 """ 238 Return list of choices (tuple (key, value)) for hours select. 239 """ 240 # hour 24H format with leading 0 241 return [(i, '%02d' % i) for i in range(0, 24)] 242 243 def minute_choices(self, fmt): 244 """ 245 Return list of choices (tuple (key, value)) for minutes select. 246 """ 247 # minutes with leading 0 248 return [(i, '%02d' % i) for i in range(0, 60)] 249 250 def second_choices(self, fmt): 251 """ 252 Return list of choices (tuple (key, value)) for seconds select. 253 """ 254 # seconds with leading 0 255 return [(i, '%02d' % i) for i in range(0, 60)] 256 No newline at end of file -
tests/regressiontests/forms/extra.py
20 20 # SelectDateWidget ############################################################ 21 21 22 22 >>> from django.forms.extras import SelectDateWidget 23 >>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016') )23 >>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), format='FjY') 24 24 >>> print w.render('mydate', '') 25 25 <select name="mydate_month" id="id_mydate_month"> 26 <option value=" 0">---</option>26 <option value="-1">---</option> 27 27 <option value="1">January</option> 28 28 <option value="2">February</option> 29 29 <option value="3">March</option> … … 38 38 <option value="12">December</option> 39 39 </select> 40 40 <select name="mydate_day" id="id_mydate_day"> 41 <option value=" 0">---</option>41 <option value="-1">---</option> 42 42 <option value="1">1</option> 43 43 <option value="2">2</option> 44 44 <option value="3">3</option> … … 72 72 <option value="31">31</option> 73 73 </select> 74 74 <select name="mydate_year" id="id_mydate_year"> 75 <option value=" 0">---</option>75 <option value="-1">---</option> 76 76 <option value="2007">2007</option> 77 77 <option value="2008">2008</option> 78 78 <option value="2009">2009</option> … … 219 219 >>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), required=False) 220 220 >>> print w.render('mydate', '') 221 221 <select name="mydate_month" id="id_mydate_month"> 222 <option value=" 0">---</option>223 <option value="1">Jan uary</option>224 <option value="2">Feb ruary</option>222 <option value="-1">---</option> 223 <option value="1">Jan.</option> 224 <option value="2">Feb.</option> 225 225 <option value="3">March</option> 226 226 <option value="4">April</option> 227 227 <option value="5">May</option> 228 228 <option value="6">June</option> 229 229 <option value="7">July</option> 230 <option value="8">Aug ust</option>231 <option value="9">Sept ember</option>232 <option value="10">Oct ober</option>233 <option value="11">Nov ember</option>234 <option value="12">Dec ember</option>230 <option value="8">Aug.</option> 231 <option value="9">Sept.</option> 232 <option value="10">Oct.</option> 233 <option value="11">Nov.</option> 234 <option value="12">Dec.</option> 235 235 </select> 236 236 <select name="mydate_day" id="id_mydate_day"> 237 <option value=" 0">---</option>237 <option value="-1">---</option> 238 238 <option value="1">1</option> 239 239 <option value="2">2</option> 240 240 <option value="3">3</option> … … 268 268 <option value="31">31</option> 269 269 </select> 270 270 <select name="mydate_year" id="id_mydate_year"> 271 <option value=" 0">---</option>271 <option value="-1">---</option> 272 272 <option value="2007">2007</option> 273 273 <option value="2008">2008</option> 274 274 <option value="2009">2009</option> … … 282 282 </select> 283 283 >>> print w.render('mydate', '2010-04-15') 284 284 <select name="mydate_month" id="id_mydate_month"> 285 <option value=" 0">---</option>286 <option value="1">Jan uary</option>287 <option value="2">Feb ruary</option>285 <option value="-1">---</option> 286 <option value="1">Jan.</option> 287 <option value="2">Feb.</option> 288 288 <option value="3">March</option> 289 289 <option value="4" selected="selected">April</option> 290 290 <option value="5">May</option> 291 291 <option value="6">June</option> 292 292 <option value="7">July</option> 293 <option value="8">Aug ust</option>294 <option value="9">Sept ember</option>295 <option value="10">Oct ober</option>296 <option value="11">Nov ember</option>297 <option value="12">Dec ember</option>293 <option value="8">Aug.</option> 294 <option value="9">Sept.</option> 295 <option value="10">Oct.</option> 296 <option value="11">Nov.</option> 297 <option value="12">Dec.</option> 298 298 </select> 299 299 <select name="mydate_day" id="id_mydate_day"> 300 <option value=" 0">---</option>300 <option value="-1">---</option> 301 301 <option value="1">1</option> 302 302 <option value="2">2</option> 303 303 <option value="3">3</option> … … 331 331 <option value="31">31</option> 332 332 </select> 333 333 <select name="mydate_year" id="id_mydate_year"> 334 <option value=" 0">---</option>334 <option value="-1">---</option> 335 335 <option value="2007">2007</option> 336 336 <option value="2008">2008</option> 337 337 <option value="2009">2009</option> … … 364 364 2008-04-01 365 365 366 366 367 # SelectTimeWidget ############################################################ 368 369 >>> from django.forms.extras import SelectTimeWidget 370 >>> w = SelectTimeWidget() 371 >>> print w.render('mytime', '') 372 <select name="mytime_hour" id="id_mytime_hour"> 373 <option value="-1">---</option> 374 <option value="0">00</option> 375 <option value="1">01</option> 376 <option value="2">02</option> 377 <option value="3">03</option> 378 <option value="4">04</option> 379 <option value="5">05</option> 380 <option value="6">06</option> 381 <option value="7">07</option> 382 <option value="8">08</option> 383 <option value="9">09</option> 384 <option value="10">10</option> 385 <option value="11">11</option> 386 <option value="12">12</option> 387 <option value="13">13</option> 388 <option value="14">14</option> 389 <option value="15">15</option> 390 <option value="16">16</option> 391 <option value="17">17</option> 392 <option value="18">18</option> 393 <option value="19">19</option> 394 <option value="20">20</option> 395 <option value="21">21</option> 396 <option value="22">22</option> 397 <option value="23">23</option> 398 </select> 399 <select name="mytime_minute" id="id_mytime_minute"> 400 <option value="-1">---</option> 401 <option value="0">00</option> 402 <option value="1">01</option> 403 <option value="2">02</option> 404 <option value="3">03</option> 405 <option value="4">04</option> 406 <option value="5">05</option> 407 <option value="6">06</option> 408 <option value="7">07</option> 409 <option value="8">08</option> 410 <option value="9">09</option> 411 <option value="10">10</option> 412 <option value="11">11</option> 413 <option value="12">12</option> 414 <option value="13">13</option> 415 <option value="14">14</option> 416 <option value="15">15</option> 417 <option value="16">16</option> 418 <option value="17">17</option> 419 <option value="18">18</option> 420 <option value="19">19</option> 421 <option value="20">20</option> 422 <option value="21">21</option> 423 <option value="22">22</option> 424 <option value="23">23</option> 425 <option value="24">24</option> 426 <option value="25">25</option> 427 <option value="26">26</option> 428 <option value="27">27</option> 429 <option value="28">28</option> 430 <option value="29">29</option> 431 <option value="30">30</option> 432 <option value="31">31</option> 433 <option value="32">32</option> 434 <option value="33">33</option> 435 <option value="34">34</option> 436 <option value="35">35</option> 437 <option value="36">36</option> 438 <option value="37">37</option> 439 <option value="38">38</option> 440 <option value="39">39</option> 441 <option value="40">40</option> 442 <option value="41">41</option> 443 <option value="42">42</option> 444 <option value="43">43</option> 445 <option value="44">44</option> 446 <option value="45">45</option> 447 <option value="46">46</option> 448 <option value="47">47</option> 449 <option value="48">48</option> 450 <option value="49">49</option> 451 <option value="50">50</option> 452 <option value="51">51</option> 453 <option value="52">52</option> 454 <option value="53">53</option> 455 <option value="54">54</option> 456 <option value="55">55</option> 457 <option value="56">56</option> 458 <option value="57">57</option> 459 <option value="58">58</option> 460 <option value="59">59</option> 461 </select> 462 >>> w = SelectTimeWidget(required=False) 463 >>> print w.render('mytime', '15:45') 464 <select name="mytime_hour" id="id_mytime_hour"> 465 <option value="-1">---</option> 466 <option value="0">00</option> 467 <option value="1">01</option> 468 <option value="2">02</option> 469 <option value="3">03</option> 470 <option value="4">04</option> 471 <option value="5">05</option> 472 <option value="6">06</option> 473 <option value="7">07</option> 474 <option value="8">08</option> 475 <option value="9">09</option> 476 <option value="10">10</option> 477 <option value="11">11</option> 478 <option value="12">12</option> 479 <option value="13">13</option> 480 <option value="14">14</option> 481 <option value="15" selected="selected">15</option> 482 <option value="16">16</option> 483 <option value="17">17</option> 484 <option value="18">18</option> 485 <option value="19">19</option> 486 <option value="20">20</option> 487 <option value="21">21</option> 488 <option value="22">22</option> 489 <option value="23">23</option> 490 </select> 491 <select name="mytime_minute" id="id_mytime_minute"> 492 <option value="-1">---</option> 493 <option value="0">00</option> 494 <option value="1">01</option> 495 <option value="2">02</option> 496 <option value="3">03</option> 497 <option value="4">04</option> 498 <option value="5">05</option> 499 <option value="6">06</option> 500 <option value="7">07</option> 501 <option value="8">08</option> 502 <option value="9">09</option> 503 <option value="10">10</option> 504 <option value="11">11</option> 505 <option value="12">12</option> 506 <option value="13">13</option> 507 <option value="14">14</option> 508 <option value="15">15</option> 509 <option value="16">16</option> 510 <option value="17">17</option> 511 <option value="18">18</option> 512 <option value="19">19</option> 513 <option value="20">20</option> 514 <option value="21">21</option> 515 <option value="22">22</option> 516 <option value="23">23</option> 517 <option value="24">24</option> 518 <option value="25">25</option> 519 <option value="26">26</option> 520 <option value="27">27</option> 521 <option value="28">28</option> 522 <option value="29">29</option> 523 <option value="30">30</option> 524 <option value="31">31</option> 525 <option value="32">32</option> 526 <option value="33">33</option> 527 <option value="34">34</option> 528 <option value="35">35</option> 529 <option value="36">36</option> 530 <option value="37">37</option> 531 <option value="38">38</option> 532 <option value="39">39</option> 533 <option value="40">40</option> 534 <option value="41">41</option> 535 <option value="42">42</option> 536 <option value="43">43</option> 537 <option value="44">44</option> 538 <option value="45" selected="selected">45</option> 539 <option value="46">46</option> 540 <option value="47">47</option> 541 <option value="48">48</option> 542 <option value="49">49</option> 543 <option value="50">50</option> 544 <option value="51">51</option> 545 <option value="52">52</option> 546 <option value="53">53</option> 547 <option value="54">54</option> 548 <option value="55">55</option> 549 <option value="56">56</option> 550 <option value="57">57</option> 551 <option value="58">58</option> 552 <option value="59">59</option> 553 </select> 554 >>> w = SelectTimeWidget(required=True) 555 >>> print w.render('mytime', '15:45') 556 <select name="mytime_hour" id="id_mytime_hour"> 557 <option value="0">00</option> 558 <option value="1">01</option> 559 <option value="2">02</option> 560 <option value="3">03</option> 561 <option value="4">04</option> 562 <option value="5">05</option> 563 <option value="6">06</option> 564 <option value="7">07</option> 565 <option value="8">08</option> 566 <option value="9">09</option> 567 <option value="10">10</option> 568 <option value="11">11</option> 569 <option value="12">12</option> 570 <option value="13">13</option> 571 <option value="14">14</option> 572 <option value="15" selected="selected">15</option> 573 <option value="16">16</option> 574 <option value="17">17</option> 575 <option value="18">18</option> 576 <option value="19">19</option> 577 <option value="20">20</option> 578 <option value="21">21</option> 579 <option value="22">22</option> 580 <option value="23">23</option> 581 </select> 582 <select name="mytime_minute" id="id_mytime_minute"> 583 <option value="0">00</option> 584 <option value="1">01</option> 585 <option value="2">02</option> 586 <option value="3">03</option> 587 <option value="4">04</option> 588 <option value="5">05</option> 589 <option value="6">06</option> 590 <option value="7">07</option> 591 <option value="8">08</option> 592 <option value="9">09</option> 593 <option value="10">10</option> 594 <option value="11">11</option> 595 <option value="12">12</option> 596 <option value="13">13</option> 597 <option value="14">14</option> 598 <option value="15">15</option> 599 <option value="16">16</option> 600 <option value="17">17</option> 601 <option value="18">18</option> 602 <option value="19">19</option> 603 <option value="20">20</option> 604 <option value="21">21</option> 605 <option value="22">22</option> 606 <option value="23">23</option> 607 <option value="24">24</option> 608 <option value="25">25</option> 609 <option value="26">26</option> 610 <option value="27">27</option> 611 <option value="28">28</option> 612 <option value="29">29</option> 613 <option value="30">30</option> 614 <option value="31">31</option> 615 <option value="32">32</option> 616 <option value="33">33</option> 617 <option value="34">34</option> 618 <option value="35">35</option> 619 <option value="36">36</option> 620 <option value="37">37</option> 621 <option value="38">38</option> 622 <option value="39">39</option> 623 <option value="40">40</option> 624 <option value="41">41</option> 625 <option value="42">42</option> 626 <option value="43">43</option> 627 <option value="44">44</option> 628 <option value="45" selected="selected">45</option> 629 <option value="46">46</option> 630 <option value="47">47</option> 631 <option value="48">48</option> 632 <option value="49">49</option> 633 <option value="50">50</option> 634 <option value="51">51</option> 635 <option value="52">52</option> 636 <option value="53">53</option> 637 <option value="54">54</option> 638 <option value="55">55</option> 639 <option value="56">56</option> 640 <option value="57">57</option> 641 <option value="58">58</option> 642 <option value="59">59</option> 643 </select> 644 645 Accepts a datetime or a string: 646 647 >>> w.render('mydate', datetime.time(15, 45, 15)) == w.render('mydate', '15:45:15') 648 True 649 650 Using a SelectDateWidget in a form: 651 652 >>> class GetTime(Form): 653 ... mytime = TimeField(widget=SelectTimeWidget) 654 >>> a = GetTime({'mytime_hour':'15', 'mytime_minute':'45', 'mytime_second':'15'}) 655 >>> print a.is_valid() 656 True 657 >>> print a.cleaned_data['mytime'] 658 15:45:15 659 660 As with any widget that implements get_value_from_datadict, 661 we must be prepared to accept the input from the "as_hidden" 662 rendering as well. 663 664 >>> print a['mytime'].as_hidden() 665 <input type="hidden" name="mytime" value="15:45:15" id="id_mytime" /> 666 >>> b=GetTime({'mytime':'15:45:15'}) 667 >>> print b.is_valid() 668 True 669 >>> print b.cleaned_data['mytime'] 670 15:45:15 671 672 367 673 # MultiWidget and MultiValueField ############################################# 368 674 # MultiWidgets are widgets composed of other widgets. They are usually 369 675 # combined with MultiValueFields - a field that is composed of other fields.