Ticket #13621: ticket13621.diff
File ticket13621.diff, 12.1 KB (added by , 14 years ago) |
---|
-
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 1f8ff6d..9c5379a 100644
a b from django import forms, template 2 2 from django.forms.formsets import all_valid 3 3 from django.forms.models import modelform_factory, modelformset_factory, inlineformset_factory 4 4 from django.forms.models import BaseInlineFormSet 5 from django.conf import settings 5 6 from django.contrib.contenttypes.models import ContentType 6 7 from django.contrib.admin import widgets 7 8 from django.contrib.admin import helpers … … class BaseModelAdmin(object): 116 117 for klass in db_field.__class__.mro(): 117 118 if klass in self.formfield_overrides: 118 119 kwargs = dict(self.formfield_overrides[klass], **kwargs) 120 if settings.USE_L10N and 'localize' not in kwargs: 121 kwargs['localize']=True 119 122 return db_field.formfield(**kwargs) 120 123 121 124 # For any other type of field, just call its formfield() method. 125 if settings.USE_L10N and 'localize' not in kwargs: 126 kwargs['localize'] = True 122 127 return db_field.formfield(**kwargs) 123 128 124 129 def formfield_for_choice_field(self, db_field, request=None, **kwargs): -
django/forms/fields.py
diff --git a/django/forms/fields.py b/django/forms/fields.py index 0bae4ba..0026f59 100644
a b class Field(object): 107 107 self.localize = localize 108 108 if self.localize: 109 109 widget.is_localized = True 110 if hasattr(self, 'input_formats'): 111 widget.input_formats = self.input_formats 110 112 111 113 # Hook into self.widget_attrs() for any Field-specific HTML attributes. 112 114 extra_attrs = self.widget_attrs(widget) … … class DateField(Field): 323 325 } 324 326 325 327 def __init__(self, input_formats=None, *args, **kwargs): 326 super(DateField, self).__init__(*args, **kwargs)327 328 self.input_formats = input_formats 329 super(DateField, self).__init__(*args, **kwargs) 328 330 329 331 def to_python(self, value): 330 332 """ … … class TimeField(Field): 351 353 } 352 354 353 355 def __init__(self, input_formats=None, *args, **kwargs): 354 super(TimeField, self).__init__(*args, **kwargs)355 356 self.input_formats = input_formats 357 super(TimeField, self).__init__(*args, **kwargs) 356 358 357 359 def to_python(self, value): 358 360 """ … … class DateTimeField(Field): 377 379 } 378 380 379 381 def __init__(self, input_formats=None, *args, **kwargs): 380 super(DateTimeField, self).__init__(*args, **kwargs)381 382 self.input_formats = input_formats 383 super(DateTimeField, self).__init__(*args, **kwargs) 382 384 383 385 def to_python(self, value): 384 386 """ -
django/forms/widgets.py
diff --git a/django/forms/widgets.py b/django/forms/widgets.py index e3799c6..f9ed445 100644
a b class Widget(object): 134 134 is_hidden = False # Determines whether this corresponds to an <input type="hidden">. 135 135 needs_multipart_form = False # Determines does this widget need multipart-encrypted form 136 136 is_localized = False 137 input_formats = None # Input formats explicitly specified for the form field 137 138 138 139 def __init__(self, attrs=None): 139 140 if attrs is not None: … … class Textarea(Widget): 302 303 303 304 class DateInput(Input): 304 305 input_type = 'text' 305 format = '%Y-%m-%d' # '2006-10-25' 306 fallback_format = '%Y-%m-%d' # '2006-10-25' 307 format = None 306 308 307 309 def __init__(self, attrs=None, format=None): 308 310 super(DateInput, self).__init__(attrs) … … class DateInput(Input): 310 312 self.format = format 311 313 312 314 def _format_value(self, value): 315 base_format = self.format 316 if self.format is None and self.input_formats: 317 base_format = self.input_formats[0] 318 313 319 if self.is_localized: 314 return formats.localize_input(value )320 return formats.localize_input(value, default=base_format) 315 321 elif hasattr(value, 'strftime'): 316 322 value = datetime_safe.new_date(value) 317 return value.strftime(self.format) 323 return value.strftime(base_format is not None\ 324 and base_format or self.fallback_format) 318 325 return value 319 326 320 327 def _has_changed(self, initial, data): … … class DateInput(Input): 330 337 331 338 class DateTimeInput(Input): 332 339 input_type = 'text' 333 format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59' 340 fallback_format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59' 341 format = None 334 342 335 343 def __init__(self, attrs=None, format=None): 336 344 super(DateTimeInput, self).__init__(attrs) … … class DateTimeInput(Input): 338 346 self.format = format 339 347 340 348 def _format_value(self, value): 349 base_format = self.format 350 if self.format is None and self.input_formats: 351 base_format = self.input_formats[0] 352 341 353 if self.is_localized: 342 return formats.localize_input(value )354 return formats.localize_input(value, default=base_format) 343 355 elif hasattr(value, 'strftime'): 344 356 value = datetime_safe.new_datetime(value) 345 return value.strftime(self.format) 357 return value.strftime(base_format is not None\ 358 and base_format or self.fallback_format) 346 359 return value 347 360 348 361 def _has_changed(self, initial, data): … … class DateTimeInput(Input): 358 371 359 372 class TimeInput(Input): 360 373 input_type = 'text' 361 format = '%H:%M:%S' # '14:30:59' 374 fallback_format = '%H:%M:%S' # '14:30:59' 375 format = None 362 376 363 377 def __init__(self, attrs=None, format=None): 364 378 super(TimeInput, self).__init__(attrs) … … class TimeInput(Input): 366 380 self.format = format 367 381 368 382 def _format_value(self, value): 383 base_format = self.format 384 if self.format is None and self.input_formats: 385 base_format = self.input_formats[0] 386 369 387 if self.is_localized: 370 return formats.localize_input(value )388 return formats.localize_input(value, default=base_format) 371 389 elif hasattr(value, 'strftime'): 372 return value.strftime(self.format) 390 return value.strftime(base_format is not None\ 391 and base_format or self.fallback_format) 373 392 return value 374 393 375 394 def _has_changed(self, initial, data): … … class SplitDateTimeWidget(MultiWidget): 764 783 return [value.date(), value.time().replace(microsecond=0)] 765 784 return [None, None] 766 785 786 def set_date_format(self, fmt): 787 self.widgets[0].format = fmt 788 789 def set_time_format(self, fmt): 790 self.widgets[1].format = fmt 791 767 792 class SplitHiddenDateTimeWidget(SplitDateTimeWidget): 768 793 """ 769 794 A Widget that splits datetime input into two <input type="hidden"> inputs. -
tests/regressiontests/forms/fields.py
diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index 990a9f7..bbd251a 100644
a b class FieldsTests(TestCase): 350 350 self.assertEqual(None, f.clean('')) 351 351 self.assertEqual('None', repr(f.clean(''))) 352 352 353 def test_ticket13621_localized_inputformats(self): 354 # Explicit input formats should have precedence over any 355 # other format specification. 356 357 f = TimeField(input_formats=["%I:%M %p"], widget=TimeInput, 358 localize=True) 359 result = f.clean('1:30 PM') 360 self.assertNotEqual(None, result) 361 text = f.widget._format_value(result) 362 self.assertNotEqual(None, f.clean(text)) 363 364 f = DateTimeField(input_formats=["%I:%M %p"], localize=True) 365 result = f.clean('1:30 PM') 366 text = f.widget._format_value(result) 367 f.clean(text) 368 self.assertNotEqual(None, f.clean(text)) 369 370 f = DateField(input_formats=["%I:%M %p"], localize=True) 371 result = f.clean('1:30 PM') 372 text = f.widget._format_value(result) 373 f.clean(text) 374 self.assertNotEqual(None, f.clean(text)) 375 376 # If no localization should be used and input_formats are 377 # provided, use them (or actually the first in the list). 378 379 380 f = DateTimeField(input_formats=["%I:%M %p"], localize=False) 381 result = f.clean('1:30 PM') 382 text = f.widget._format_value(result) 383 f.clean(text) 384 self.assertNotEqual(None, f.clean(text)) 385 386 f = DateField(input_formats=["%I:%M %p"], localize=False) 387 result = f.clean('1:30 PM') 388 text = f.widget._format_value(result) 389 f.clean(text) 390 self.assertNotEqual(None, f.clean(text)) 391 392 f = TimeField(widget=TimeInput) 393 result = f.clean('12:30:00') 394 self.assertNotEqual(None, result) 395 text = f.widget._format_value(result) 396 self.assertNotEqual(None, f.clean(text)) 397 398 f = DateTimeField() 399 result = f.clean('2006-10-25 12:30:00') 400 self.assertNotEqual(None, result) 401 text = f.widget._format_value(result) 402 self.assertNotEqual(None, f.clean(text)) 403 404 def test_ticket13621_timefield_notlocalized(self): 405 f = TimeField(input_formats=["%I:%M %p"], widget=TimeInput, 406 localize=False) 407 result = f.clean('1:30 PM') 408 self.assertNotEqual(None, result) 409 text = f.widget._format_value(result) 410 self.assertNotEqual(None, f.clean(text)) 411 412 def test_ticket13621_datefield_fallback(self): 413 f = DateField(widget=DateInput) 414 result = f.clean('2006-10-25') 415 self.assertNotEqual(None, result) 416 text = f.widget._format_value(result) 417 self.assertNotEqual(None, f.clean(text)) 418 419 def test_ticket13621_timefield_globally_localized(self): 420 """ 421 Test if the timeinput widgets produces the same output format that it 422 accepts as input when set using a format module. 423 """ 424 from django.utils import formats 425 from django.conf import settings 426 old_setting = settings.USE_L10N 427 settings.USE_L10N = True 428 _get_format_modules = formats.get_format_modules 429 try: 430 # We have to do a bit of mocking here to get into the L10N system 431 # properly. 432 class _GetFormatModules(object): 433 mock_format_modules = None 434 435 def __call__(self, reverse=False): 436 if self.mock_format_modules is None: 437 return _get_format_modules(reverse) 438 return reverse and reversed(self.mock_format_modules)\ 439 or self.mock_format_modules 440 441 class MockFormatModule(object): 442 TIME_INPUT_FORMATS = ["%I:%M %p"] 443 DATE_INPUT_FORMATS = ["%I:%M %p"] 444 DATETIME_INPUT_FORMATS = ["%I:%M %p"] 445 446 formats.get_format_modules = _GetFormatModules() 447 formats.get_format_modules.mock_format_modules = [ 448 MockFormatModule()] 449 450 f = TimeField(localize=True) 451 result = f.clean('1:30 PM') 452 f.clean(f.widget._format_value(result)) 453 454 f = DateField(localize=True) 455 result = f.clean('1:30 PM') 456 f.clean(f.widget._format_value(result)) 457 458 f = DateTimeField(localize=True) 459 result = f.clean('1:30 PM') 460 f.clean(f.widget._format_value(result)) 461 462 # If an explicit input format is provided, use that 463 464 f = TimeField(input_formats=["%I"], localize=True) 465 result = f.clean('1') 466 f.clean(f.widget._format_value(result)) 467 468 f = DateField(input_formats=["%I"], localize=True) 469 result = f.clean('1') 470 f.clean(f.widget._format_value(result)) 471 472 f = DateTimeField(input_formats=["%I"], localize=True) 473 result = f.clean('1') 474 f.clean(f.widget._format_value(result)) 475 finally: 476 formats.get_format_modules = _get_format_modules 477 settings.USE_L10N = old_setting 478 479 353 480 # RegexField ################################################################## 354 481 355 482 def test_regexfield_27(self):