Changeset 2518
- Timestamp:
- 03/12/06 19:33:45 (3 years ago)
- Files:
-
- django/branches/magic-removal/django/db/models/base.py (modified) (4 diffs)
- django/branches/magic-removal/django/db/models/fields/__init__.py (modified) (13 diffs)
- django/branches/magic-removal/tests/modeltests/validation (added)
- django/branches/magic-removal/tests/modeltests/validation/__init__.py (added)
- django/branches/magic-removal/tests/modeltests/validation/models.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/magic-removal/django/db/models/base.py
r2506 r2518 1 1 import django.db.models.manipulators 2 2 import django.db.models.manager 3 from django.core import validators 4 from django.core.exceptions import ObjectDoesNotExist 3 5 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist 4 6 from django.db.models.fields.related import OneToOne, ManyToOne … … 10 12 from django.db.models.loading import register_models 11 13 from django.dispatch import dispatcher 12 from django.core.exceptions import ObjectDoesNotExist13 14 from django.utils.datastructures import SortedDict 14 15 from django.utils.functional import curry … … 39 40 # Build complete list of parents 40 41 for base in bases: 42 # TODO: Checking for the presence of '_meta' is hackish. 41 43 if '_meta' in dir(base): 42 44 new_class._meta.parents.append(base) … … 197 199 save.alters_data = True 198 200 201 def validate(self): 202 """ 203 First coerces all fields on this instance to their proper Python types. 204 Then runs validation on every field. Returns a dictionary of 205 field_name -> error_list. 206 """ 207 error_dict = {} 208 invalid_python = {} 209 for f in self._meta.fields: 210 try: 211 setattr(self, f.attname, f.to_python(getattr(self, f.attname, f.get_default()))) 212 except validators.ValidationError, e: 213 error_dict[f.name] = e.messages 214 invalid_python[f.name] = 1 215 for f in self._meta.fields: 216 if f.name in invalid_python: 217 continue 218 errors = f.validate_full(getattr(self, f.attname, f.get_default()), self.__dict__) 219 if errors: 220 error_dict[f.name] = errors 221 return error_dict 222 199 223 def _collect_sub_objects(self, seen_objs): 200 224 """ django/branches/magic-removal/django/db/models/fields/__init__.py
r2517 r2518 7 7 from django.utils.functional import curry, lazy 8 8 from django.utils.text import capfirst 9 from django.utils.translation import gettext _lazy, ngettext10 import datetime, os 9 from django.utils.translation import gettext, gettext_lazy, ngettext 10 import datetime, os, time 11 11 12 12 class NOT_PROVIDED: … … 38 38 if getattr(self, 'original_object', None) and self.original_object._get_pk_val() == old_obj._get_pk_val(): 39 39 return 40 raise validators.ValidationError, _("%(optname)s with this %(fieldname)s already exists.") % {'optname': capfirst(opts.verbose_name), 'fieldname': f.verbose_name}40 raise validators.ValidationError, gettext("%(optname)s with this %(fieldname)s already exists.") % {'optname': capfirst(opts.verbose_name), 'fieldname': f.verbose_name} 41 41 42 42 # A guide to Field parameters: … … 97 97 return cmp(self.creation_counter, other.creation_counter) 98 98 99 def to_python(self, value): 100 """ 101 Converts the input value into the expected Python data type, raising 102 validators.ValidationError if the data can't be converted. Returns the 103 converted value. Subclasses should override this. 104 """ 105 return value 106 107 def validate_full(self, field_data, all_data): 108 """ 109 Returns a list of errors for this field. This is the main interface, 110 as it encapsulates some basic validation logic used by all fields. 111 Subclasses should implement validate(), not validate_full(). 112 """ 113 if not self.blank and not field_data: 114 return [gettext_lazy('This field is required.')] 115 try: 116 self.validate(field_data, all_data) 117 except validators.ValidationError, e: 118 return e.messages 119 return [] 120 121 def validate(self, field_data, all_data): 122 """ 123 Raises validators.ValidationError if field_data has any errors. 124 Subclasses should override this to specify field-specific validation 125 logic. This method should assume field_data has already been converted 126 into the appropriate data type by Field.to_python(). 127 """ 128 pass 129 99 130 def set_attributes_from_name(self, name): 100 131 self.name = name … … 300 331 def __init__(self, *args, **kwargs): 301 332 assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__ 333 kwargs['blank'] = True 302 334 Field.__init__(self, *args, **kwargs) 335 336 def to_python(self, value): 337 if value is None: 338 return value 339 try: 340 return int(value) 341 except (TypeError, ValueError): 342 raise validators.ValidationError, gettext("This value must be an integer.") 303 343 304 344 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): … … 328 368 Field.__init__(self, *args, **kwargs) 329 369 370 def to_python(self, value): 371 if value in (True, False): return value 372 if value is 't': return True 373 if value is 'f': return False 374 raise validators.ValidationError, gettext("This value must be either True or False.") 375 330 376 def get_manipulator_field_objs(self): 331 377 return [forms.CheckboxField] … … 335 381 return [forms.TextField] 336 382 383 def to_python(self, value): 384 if isinstance(value, basestring): 385 return value 386 if value is None: 387 if self.null: 388 return value 389 else: 390 raise validators.ValidationError, gettext_lazy("This field cannot be null.") 391 return str(value) 392 393 # TODO: Maybe move this into contrib, because it's specialized. 337 394 class CommaSeparatedIntegerField(CharField): 338 395 def get_manipulator_field_objs(self): … … 349 406 Field.__init__(self, verbose_name, name, **kwargs) 350 407 408 def to_python(self, value): 409 if isinstance(value, datetime.datetime): 410 return value.date() 411 if isinstance(value, datetime.date): 412 return value 413 validators.isValidANSIDate(value, None) 414 return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3]) 415 351 416 def get_db_prep_lookup(self, lookup_type, value): 352 417 if lookup_type == 'range': … … 392 457 393 458 class DateTimeField(DateField): 459 def to_python(self, value): 460 if isinstance(value, datetime.datetime): 461 return value 462 if isinstance(value, datetime.date): 463 return datetime.datetime(value.year, value.month, value.day) 464 try: # Seconds are optional, so try converting seconds first. 465 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 466 except ValueError: 467 try: # Try without seconds. 468 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 469 except ValueError: # Try without hour/minutes/seconds. 470 try: 471 return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 472 except ValueError: 473 raise validators.ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 474 394 475 def get_db_prep_save(self, value): 395 476 # Casts dates into string format for entry into database. … … 433 514 time_field: (val is not None and val.strftime("%H:%M:%S") or '')} 434 515 435 class EmailField( Field):516 class EmailField(CharField): 436 517 def __init__(self, *args, **kwargs): 437 518 kwargs['maxlength'] = 75 438 Field.__init__(self, *args, **kwargs)519 CharField.__init__(self, *args, **kwargs) 439 520 440 521 def get_internal_type(self): … … 443 524 def get_manipulator_field_objs(self): 444 525 return [forms.EmailField] 526 527 def validate(self, field_data, all_data): 528 validators.isValidEmail(field_data, all_data) 445 529 446 530 class FileField(Field): … … 584 668 return [forms.IPAddressField] 585 669 670 def validate(self, field_data, all_data): 671 validators.isValidIPAddress4(field_data, None) 672 586 673 class NullBooleanField(Field): 587 674 def __init__(self, *args, **kwargs): … … 595 682 def get_manipulator_field_objs(self): 596 683 return [forms.PhoneNumberField] 684 685 def validate(self, field_data, all_data): 686 validators.isValidPhone(field_data, all_data) 597 687 598 688 class PositiveIntegerField(IntegerField): … … 627 717 empty_strings_allowed = False 628 718 def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs): 629 self.auto_now, self.auto_now_add = auto_now, auto_now_add719 self.auto_now, self.auto_now_add = auto_now, auto_now_add 630 720 if auto_now or auto_now_add: 631 721 kwargs['editable'] = False
