Ticket #6845: 6845-against-9226.diff
File 6845-against-9226.diff, 37.2 KB (added by , 16 years ago) |
---|
-
django/contrib/contenttypes/generic.py
diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index 0504592..375f82d 100644
a b class BaseGenericInlineFormSet(BaseModelFormSet): 313 313 self.ct_fk_field.name: self.instance.pk, 314 314 }) 315 315 316 def save_new(self, form, commit=True):316 def _construct_form(self, i, **kwargs): 317 317 # Avoid a circular import. 318 318 from django.contrib.contenttypes.models import ContentType 319 kwargs = { 320 self.ct_field.get_attname(): ContentType.objects.get_for_model(self.instance).pk, 321 self.ct_fk_field.get_attname(): self.instance.pk, 322 } 319 form = super(BaseGenericInlineFormSet, self)._construct_form(i, **kwargs) 320 if self.save_as_new: 321 # Remove the key from the form's data, we are only 322 # creating new instances 323 form.data[form.add_prefix(self.ct_fk_field.name)] = None 324 form.data[form.add_prefix(self.ct_field.name)] = None 325 326 # set the GenericFK value here so that the form can do it's validation 327 setattr(form.instance, self.ct_fk_field.attname, self.instance.pk) 328 setattr(form.instance, self.ct_field.attname, ContentType.objects.get_for_model(self.instance).pk) 329 return form 330 331 def save_new(self, form, commit=True): 323 332 new_obj = self.model(**kwargs) 324 333 return save_instance(form, new_obj, commit=commit) 325 334 -
django/contrib/localflavor/au/forms.py
diff --git a/django/contrib/localflavor/au/forms.py b/django/contrib/localflavor/au/forms.py index afc3a0c..4e8a204 100644
a b Australian-specific Form helpers 4 4 5 5 from django.forms import ValidationError 6 6 from django.forms.fields import Field, RegexField, Select, EMPTY_VALUES 7 from django. forms.utilimport smart_unicode7 from django.utils.encoding import smart_unicode 8 8 from django.utils.translation import ugettext_lazy as _ 9 9 import re 10 10 -
django/contrib/localflavor/ca/forms.py
diff --git a/django/contrib/localflavor/ca/forms.py b/django/contrib/localflavor/ca/forms.py index 327d938..9544268 100644
a b Canada-specific Form helpers 4 4 5 5 from django.forms import ValidationError 6 6 from django.forms.fields import Field, RegexField, Select, EMPTY_VALUES 7 from django. forms.utilimport smart_unicode7 from django.utils.encoding import smart_unicode 8 8 from django.utils.translation import ugettext_lazy as _ 9 9 import re 10 10 -
django/core/exceptions.py
diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 1c21031..c0bcbae 100644
a b class FieldError(Exception): 32 32 """Some kind of problem with a model field.""" 33 33 pass 34 34 35 NON_FIELD_ERRORS = '__all__' 35 36 class ValidationError(Exception): 36 37 """An error while validating data.""" 37 pass 38 def __init__(self, message): 39 import operator 40 from django.utils.encoding import force_unicode 41 """ 42 ValidationError can be passed any object that can be printed (usually 43 a string), a list of objects or a dictionary. 44 """ 45 if isinstance(message, dict): 46 self.message_dict = message 47 message = reduce(operator.add, message.values()) 48 49 if isinstance(message, list): 50 self.messages = [force_unicode(msg) for msg in message] 51 else: 52 message = force_unicode(message) 53 self.messages = [message] 54 55 56 57 def __str__(self): 58 # This is needed because, without a __str__(), printing an exception 59 # instance would result in this: 60 # AttributeError: ValidationError instance has no attribute 'args' 61 # See http://www.python.org/doc/current/tut/node10.html#handling 62 if hasattr(self, 'message_dict'): 63 return repr(self.message_dict) 64 return repr(self.messages) -
django/db/models/base.py
diff --git a/django/db/models/base.py b/django/db/models/base.py index f94d25c..d8558f0 100644
a b except NameError: 9 9 from sets import Set as set # Python 2.3 fallback. 10 10 11 11 import django.db.models.manager # Imported to register signal handler. 12 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError 12 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS 13 13 from django.db.models.fields import AutoField 14 14 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 15 15 from django.db.models.query import delete_objects, Q, CollectedObjects … … from django.db.models import signals 19 19 from django.db.models.loading import register_models, get_model 20 20 from django.utils.functional import curry 21 21 from django.utils.encoding import smart_str, force_unicode, smart_unicode 22 from django.utils.text import get_text_list, capfirst 23 from django.utils.translation import ugettext_lazy as _ 22 24 from django.conf import settings 23 25 24 26 … … class Model(object): 477 479 setattr(self, cachename, obj) 478 480 return getattr(self, cachename) 479 481 482 def validate_unique(self): 483 # Gather a list of checks to perform. 484 unique_checks = self._meta.unique_together[:] 485 486 errors = {} 487 488 # Gather a list of checks for fields declared as unique and add them to 489 # the list of checks. 490 for f in self._meta.fields: 491 # MySQL can't handle ... WHERE pk IS NULL, so make sure we 492 # don't generate queries of that form. 493 is_null_pk = f.primary_key and self.pk is None 494 if f.unique and not is_null_pk: 495 unique_checks.append((f.name,)) 496 497 # FIXME: Don't run unique checks on fields that already have an error. 498 # unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]] 499 500 for unique_check in unique_checks: 501 # Try to look up an existing object with the same values as this 502 # object's values for all the unique field. 503 504 lookup_kwargs = {} 505 for field_name in unique_check: 506 f = self._meta.get_field(field_name) 507 lookup_kwargs[field_name] = getattr(self, f.attname) 508 509 qs = self.__class__._default_manager.filter(**lookup_kwargs) 510 511 # Exclude the current object from the query if we are validating an 512 # already existing instance (as opposed to a new one) 513 if self.pk is not None: 514 qs = qs.exclude(pk=self.pk) 515 516 # This cute trick with extra/values is the most efficient way to 517 # tell if a particular query returns any results. 518 if qs.extra(select={'a': 1}).values('a').order_by(): 519 model_name = capfirst(self._meta.verbose_name) 520 521 # A unique field 522 if len(unique_check) == 1: 523 field_name = unique_check[0] 524 field_label = capfirst(self._meta.get_field(field_name).verbose_name) 525 # Insert the error into the error dict, very sneaky 526 errors[field_name] = [ 527 _(u"%(model_name)s with this %(field_label)s already exists.") % \ 528 {'model_name': unicode(model_name), 529 'field_label': unicode(field_label)} 530 ] 531 # unique_together 532 else: 533 field_labels = [capfirst(self._meta.get_field(field_name).verbose_name) for field_name in unique_check] 534 field_labels = get_text_list(field_labels, _('and')) 535 errors.setdefault(NON_FIELD_ERRORS, []).append( 536 _(u"%(model_name)s with this %(field_label)s already exists.") % \ 537 {'model_name': unicode(model_name), 538 'field_label': unicode(field_labels)} 539 ) 540 541 if errors: 542 # Raise the collected errors 543 raise ValidationError(errors) 544 545 def validate(self): 546 """ 547 Hook for doing any extra model-wide validation after Model.clean() been 548 called on every field. Any ValidationError raised by this method will 549 not be associated with a particular field; it will have a special-case 550 association with the field named '__all__'. 551 """ 552 self.validate_unique() 553 554 def clean(self): 555 """ 556 Cleans all fields and raises ValidationError containing message_dict of 557 all validation errors if any occur. 558 """ 559 errors = {} 560 for f in self._meta.fields: 561 try: 562 setattr(self, f.attname, f.clean(getattr(self, f.attname), self)) 563 except ValidationError, e: 564 errors[f.name] = e.messages 565 try: 566 # TODO: run this only if not errors?? 567 self.validate() 568 except ValidationError, e: 569 if hasattr(e, 'message_dict'): 570 if errors: 571 for k, v in e.message_dict.items(): 572 errors.set_default(k, []).extend(v) 573 else: 574 errors = e.message_dict 575 else: 576 errors[NON_FIELD_ERRORS] = e.messages 577 578 if errors: 579 raise ValidationError(errors) 580 480 581 481 582 482 583 ############################################ -
django/db/models/fields/__init__.py
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index afa1c13..89cc7f6 100644
a b class Field(object): 117 117 Returns the converted value. Subclasses should override this. 118 118 """ 119 119 return value 120 121 def validate(self, value, model_instance): 122 """ 123 Validates value and throws ValidationError. Subclasses should override 124 this to provide validation logic. 125 """ 126 if not self.editable: 127 # skip validation for non-editable fields 128 return 129 if self._choices and value: 130 if not value in dict(self.choices): 131 raise exceptions.ValidationError(_('Value %r is not a valid choice.') % value) 132 133 if value is None and not self.null: 134 raise exceptions.ValidationError( 135 ugettext_lazy("This field cannot be null.")) 136 137 def clean(self, value, model_instance): 138 """ 139 Convert the value's type and wun validation. Validation errors from to_python 140 and validate are propagated. The correct value is returned if no error is 141 raised. 142 """ 143 value = self.to_python(value) 144 self.validate(value, model_instance) 145 return value 120 146 121 147 def db_type(self): 122 148 """ … … class AutoField(Field): 346 372 except (TypeError, ValueError): 347 373 raise exceptions.ValidationError( 348 374 _("This value must be an integer.")) 375 376 def validate(self, value, model_instance): 377 pass 349 378 350 379 def get_db_prep_value(self, value): 351 380 if value is None: … … class CharField(Field): 402 431 return "CharField" 403 432 404 433 def to_python(self, value): 405 if isinstance(value, basestring) :434 if isinstance(value, basestring) or value is None: 406 435 return value 407 if value is None:408 if self.null:409 return value410 else:411 raise exceptions.ValidationError(412 ugettext_lazy("This field cannot be null."))413 436 return smart_unicode(value) 414 437 415 438 def formfield(self, **kwargs): -
django/db/models/fields/related.py
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 1763bf2..f48498e 100644
a b class ForeignKey(RelatedField, Field): 645 645 646 646 self.db_index = True 647 647 648 def validate(self, value, model_instance): 649 if self.rel.parent_link: 650 return 651 super(ForeignKey, self).validate(value, model_instance) 652 648 653 def get_attname(self): 649 654 return '%s_id' % self.name 650 655 … … class OneToOneField(ForeignKey): 735 740 return None 736 741 return super(OneToOneField, self).formfield(**kwargs) 737 742 743 def save_form_data(self, instance, data): 744 # FIXME: is this a hack, or what? it works, but I don't really know why 745 if isinstance(data, self.rel.to): 746 setattr(instance, self.name, data) 747 else: 748 setattr(instance, self.attname, data) 749 750 738 751 class ManyToManyField(RelatedField, Field): 739 752 def __init__(self, to, **kwargs): 740 753 try: -
django/forms/__init__.py
diff --git a/django/forms/__init__.py b/django/forms/__init__.py index 0d9c68f..dc8b521 100644
a b TODO: 10 10 "This form field requires foo.js" and form.js_includes() 11 11 """ 12 12 13 from utilimport ValidationError13 from django.core.exceptions import ValidationError 14 14 from widgets import * 15 15 from fields import * 16 16 from forms import * -
django/forms/fields.py
diff --git a/django/forms/fields.py b/django/forms/fields.py index b20beb9..1d392a0 100644
a b try: 23 23 except NameError: 24 24 from sets import Set as set 25 25 26 import django.core.exceptions 26 from django.core.exceptions import ValidationError 27 27 from django.utils.translation import ugettext_lazy as _ 28 28 from django.utils.encoding import smart_unicode, smart_str 29 29 30 from util import ErrorList , ValidationError30 from util import ErrorList 31 31 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, SplitHiddenDateTimeWidget 32 32 from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile 33 33 … … class TypedChoiceField(ChoiceField): 677 677 if value == self.empty_value or value in EMPTY_VALUES: 678 678 return self.empty_value 679 679 680 # Hack alert: This field is purpose-made to use with Field.to_python as681 # a coercion function so that ModelForms with choices work. However,682 # Django's Field.to_python raises django.core.exceptions.ValidationError,683 # which is a *different* exception than684 # django.forms.utils.ValidationError. So unfortunatly we need to catch685 # both.686 680 try: 687 681 value = self.coerce(value) 688 except (ValueError, TypeError, django.core.exceptions.ValidationError):682 except (ValueError, TypeError, ValidationError): 689 683 raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) 690 684 return value 691 685 -
django/forms/forms.py
diff --git a/django/forms/forms.py b/django/forms/forms.py index 3a61826..44480f6 100644
a b Form classes 4 4 5 5 from copy import deepcopy 6 6 7 from django.core.exceptions import ValidationError 7 8 from django.utils.datastructures import SortedDict 8 9 from django.utils.html import escape 9 10 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode … … from django.utils.safestring import mark_safe 11 12 12 13 from fields import Field, FileField 13 14 from widgets import Media, media_property, TextInput, Textarea 14 from util import flatatt, ErrorDict, ErrorList , ValidationError15 from util import flatatt, ErrorDict, ErrorList 15 16 16 17 __all__ = ('BaseForm', 'Form') 17 18 … … class BaseForm(StrAndUnicode): 234 235 value = getattr(self, 'clean_%s' % name)() 235 236 self.cleaned_data[name] = value 236 237 except ValidationError, e: 237 self._errors[name] = e.messages238 self._errors[name] = self.error_class(e.messages) 238 239 if name in self.cleaned_data: 239 240 del self.cleaned_data[name] 240 241 try: 241 242 self.cleaned_data = self.clean() 242 243 except ValidationError, e: 243 self._errors[NON_FIELD_ERRORS] = e.messages244 self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages) 244 245 if self._errors: 245 246 delattr(self, 'cleaned_data') 246 247 -
django/forms/formsets.py
diff --git a/django/forms/formsets.py b/django/forms/formsets.py index 887f130..b8a86bf 100644
a b 1 1 from forms import Form 2 from django.core.exceptions import ValidationError 2 3 from django.utils.encoding import StrAndUnicode 3 4 from django.utils.safestring import mark_safe 4 5 from django.utils.translation import ugettext as _ 5 6 from fields import IntegerField, BooleanField 6 7 from widgets import Media, HiddenInput 7 from util import ErrorList , ValidationError8 from util import ErrorList 8 9 9 10 __all__ = ('BaseFormSet', 'all_valid') 10 11 -
django/forms/models.py
diff --git a/django/forms/models.py b/django/forms/models.py index acfa9ce..d5e63ef 100644
a b and database field objects. 5 5 6 6 from django.utils.encoding import smart_unicode 7 7 from django.utils.datastructures import SortedDict 8 from django.utils.text import get_text_list, capfirst9 8 from django.utils.translation import ugettext_lazy as _ 10 9 11 from util import ValidationError, ErrorList 10 from django.core.exceptions import ValidationError, NON_FIELD_ERRORS 11 from util import ErrorList 12 12 from forms import BaseForm, get_declared_fields 13 13 from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES 14 14 from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput … … __all__ = ( 26 26 'ModelMultipleChoiceField', 27 27 ) 28 28 29 30 def save_instance(form, instance, fields=None, fail_message='saved', 31 commit=True, exclude=None): 32 """ 33 Saves bound Form ``form``'s cleaned_data into model instance ``instance``. 34 35 If commit=True, then the changes to ``instance`` will be saved to the 36 database. Returns ``instance``. 37 """ 29 def make_instance(form, instance, fields=None, exclude=None): 38 30 from django.db import models 39 31 opts = instance._meta 40 if form.errors: 41 raise ValueError("The %s could not be %s because the data didn't" 42 " validate." % (opts.object_name, fail_message)) 32 43 33 cleaned_data = form.cleaned_data 44 34 for f in opts.fields: 45 35 if not f.editable or isinstance(f, models.AutoField) \ … … def save_instance(form, instance, fields=None, fail_message='saved', 49 39 continue 50 40 if exclude and f.name in exclude: 51 41 continue 42 if getattr(f.rel, 'parent_link', False) and not cleaned_data[f.name]: 43 continue 52 44 f.save_form_data(instance, cleaned_data[f.name]) 45 return instance 46 47 def save_maked_instance(form, instance, fields=None, commit=True, fail_message='saved'): 48 opts = instance._meta 49 if form.errors: 50 raise ValueError("The %s could not be %s because the data didn't" 51 " validate." % (opts.object_name, fail_message)) 53 52 # Wrap up the saving of m2m data as a function. 54 53 def save_m2m(): 55 54 opts = instance._meta … … def save_instance(form, instance, fields=None, fail_message='saved', 69 68 form.save_m2m = save_m2m 70 69 return instance 71 70 71 72 def save_instance(form, instance, fields=None, fail_message='saved', 73 commit=True, exclude=None): 74 """ 75 Saves bound Form ``form``'s cleaned_data into model instance ``instance``. 76 77 If commit=True, then the changes to ``instance`` will be saved to the 78 database. Returns ``instance``. 79 """ 80 instance = make_instance(form, instance, fields, exclude) 81 return save_maked_instance(form, instance, fields, commit, fail_message) 82 72 83 def make_model_save(model, fields, fail_message): 73 84 """Returns the save() method for a Form.""" 74 85 def save(self, commit=True): … … class BaseModelForm(BaseForm): 210 221 super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data, 211 222 error_class, label_suffix, empty_permitted) 212 223 def clean(self): 213 self.validate_unique() 224 self.instance = make_instance(self, self.instance, self._meta.fields, self._meta.exclude) 225 try: 226 self.instance.clean() 227 except ValidationError, e: 228 for k, v in e.message_dict.items(): 229 if k != NON_FIELD_ERRORS: 230 self._errors.setdefault(k, []).extend(v) 231 232 # Remove the data from the cleaned_data dict since it was invalid 233 if k in self.cleaned_data: 234 del self.cleaned_data[k] 235 236 # what about fields that don't validate but aren't present on the form? 237 if NON_FIELD_ERRORS in e.message_dict: 238 raise ValidationError(e.message_dict[NON_FIELD_ERRORS]) 239 214 240 return self.cleaned_data 215 241 216 def validate_unique(self):217 from django.db.models.fields import FieldDoesNotExist218 219 # Gather a list of checks to perform. Since this is a ModelForm, some220 # fields may have been excluded; we can't perform a unique check on a221 # form that is missing fields involved in that check.222 unique_checks = []223 for check in self.instance._meta.unique_together[:]:224 fields_on_form = [field for field in check if field in self.fields]225 if len(fields_on_form) == len(check):226 unique_checks.append(check)227 228 form_errors = []229 230 # Gather a list of checks for fields declared as unique and add them to231 # the list of checks. Again, skip fields not on the form.232 for name, field in self.fields.items():233 try:234 f = self.instance._meta.get_field_by_name(name)[0]235 except FieldDoesNotExist:236 # This is an extra field that's not on the ModelForm, ignore it237 continue238 # MySQL can't handle ... WHERE pk IS NULL, so make sure we239 # don't generate queries of that form.240 is_null_pk = f.primary_key and self.cleaned_data[name] is None241 if name in self.cleaned_data and f.unique and not is_null_pk:242 unique_checks.append((name,))243 244 # Don't run unique checks on fields that already have an error.245 unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]]246 247 bad_fields = set()248 for unique_check in unique_checks:249 # Try to look up an existing object with the same values as this250 # object's values for all the unique field.251 252 lookup_kwargs = {}253 for field_name in unique_check:254 lookup_kwargs[field_name] = self.cleaned_data[field_name]255 256 qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)257 258 # Exclude the current object from the query if we are editing an259 # instance (as opposed to creating a new one)260 if self.instance.pk is not None:261 qs = qs.exclude(pk=self.instance.pk)262 263 # This cute trick with extra/values is the most efficient way to264 # tell if a particular query returns any results.265 if qs.extra(select={'a': 1}).values('a').order_by():266 model_name = capfirst(self.instance._meta.verbose_name)267 268 # A unique field269 if len(unique_check) == 1:270 field_name = unique_check[0]271 field_label = self.fields[field_name].label272 # Insert the error into the error dict, very sneaky273 self._errors[field_name] = ErrorList([274 _(u"%(model_name)s with this %(field_label)s already exists.") % \275 {'model_name': unicode(model_name),276 'field_label': unicode(field_label)}277 ])278 # unique_together279 else:280 field_labels = [self.fields[field_name].label for field_name in unique_check]281 field_labels = get_text_list(field_labels, _('and'))282 form_errors.append(283 _(u"%(model_name)s with this %(field_label)s already exists.") % \284 {'model_name': unicode(model_name),285 'field_label': unicode(field_labels)}286 )287 288 # Mark these fields as needing to be removed from cleaned data289 # later.290 for field_name in unique_check:291 bad_fields.add(field_name)292 293 for field_name in bad_fields:294 del self.cleaned_data[field_name]295 if form_errors:296 # Raise the unique together errors since they are considered297 # form-wide.298 raise ValidationError(form_errors)299 300 242 def save(self, commit=True): 301 243 """ 302 244 Saves this ``form``'s cleaned_data into model instance … … class BaseModelForm(BaseForm): 309 251 fail_message = 'created' 310 252 else: 311 253 fail_message = 'changed' 312 return save_instance(self, self.instance, self._meta.fields, fail_message, commit) 254 255 return save_maked_instance(self, self.instance, self._meta.fields, commit, fail_message) 313 256 314 257 class ModelForm(BaseModelForm): 315 258 __metaclass__ = ModelFormMetaclass … … class BaseModelFormSet(BaseFormSet): 363 306 364 307 def save_new(self, form, commit=True): 365 308 """Saves and returns a new model instance for the given form.""" 366 return save_instance(form, self.model(), exclude=[self._pk_field.name], commit=commit)309 return form.save(commit) 367 310 368 311 def save_existing(self, form, instance, commit=True): 369 312 """Saves and returns an existing model instance for the given form.""" 370 return save_instance(form, instance, exclude=[self._pk_field.name], commit=commit)313 return form.save(commit) 371 314 372 315 def save(self, commit=True): 373 316 """Saves model instances for every form, adding and changing instances … … class BaseInlineFormSet(BaseModelFormSet): 467 410 # Remove the primary key from the form's data, we are only 468 411 # creating new instances 469 412 form.data[form.add_prefix(self._pk_field.name)] = None 413 # set the FK value here so that the form can do it's validation 414 setattr(form.instance, self.fk.get_attname(), self.instance.pk) 470 415 return form 471 416 472 417 def get_queryset(self): … … class BaseInlineFormSet(BaseModelFormSet): 477 422 kwargs = {self.fk.name: self.instance} 478 423 return self.model._default_manager.filter(**kwargs) 479 424 480 def save_new(self, form, commit=True):481 kwargs = {self.fk.get_attname(): self.instance.pk}482 new_obj = self.model(**kwargs)483 return save_instance(form, new_obj, exclude=[self._pk_field.name], commit=commit)484 485 425 def add_fields(self, form, index): 486 426 super(BaseInlineFormSet, self).add_fields(form, index) 487 427 if self._pk_field == self.fk: -
django/forms/util.py
diff --git a/django/forms/util.py b/django/forms/util.py index ea93627..9012cd8 100644
a b 1 1 from django.utils.html import conditional_escape 2 from django.utils.encoding import smart_unicode,StrAndUnicode, force_unicode2 from django.utils.encoding import StrAndUnicode, force_unicode 3 3 from django.utils.safestring import mark_safe 4 4 5 5 def flatatt(attrs): … … class ErrorList(list, StrAndUnicode): 48 48 def __repr__(self): 49 49 return repr([force_unicode(e) for e in self]) 50 50 51 class ValidationError(Exception):52 def __init__(self, message):53 """54 ValidationError can be passed any object that can be printed (usually55 a string) or a list of objects.56 """57 if isinstance(message, list):58 self.messages = ErrorList([smart_unicode(msg) for msg in message])59 else:60 message = smart_unicode(message)61 self.messages = ErrorList([message])62 63 def __str__(self):64 # This is needed because, without a __str__(), printing an exception65 # instance would result in this:66 # AttributeError: ValidationError instance has no attribute 'args'67 # See http://www.python.org/doc/current/tut/node10.html#handling68 return repr(self.messages) -
tests/modeltests/model_forms/models.py
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py index 0b99a84..12177f0 100644
a b class ImprovedArticleWithParentLink(models.Model): 74 74 article = models.OneToOneField(Article, parent_link=True) 75 75 76 76 class BetterWriter(Writer): 77 pass77 score = models.IntegerField() 78 78 79 79 class WriterProfile(models.Model): 80 80 writer = models.OneToOneField(Writer, primary_key=True) … … ValidationError: [u'Select a valid choice. 4 is not one of the available choices 850 850 >>> ImprovedArticleWithParentLinkForm.base_fields.keys() 851 851 [] 852 852 853 >>> bw = BetterWriter(name=u'Joe Better' )853 >>> bw = BetterWriter(name=u'Joe Better', score=10) 854 854 >>> bw.save() 855 855 >>> sorted(model_to_dict(bw).keys()) 856 ['id', 'name', 'writer_ptr'] 856 ['id', 'name', 'score', 'writer_ptr'] 857 858 >>> class BetterWriterForm(ModelForm): 859 ... class Meta: 860 ... model = BetterWriter 861 >>> form = BetterWriterForm({'name': 'Some Name', 'score': 12}) 862 >>> form.is_valid() 863 True 864 >>> bw2 = form.save() 865 >>> bw2.delete() 866 857 867 858 868 >>> class WriterProfileForm(ModelForm): 859 869 ... class Meta: … … False 1193 1203 >>> form._errors 1194 1204 {'__all__': [u'Price with this Price and Quantity already exists.']} 1195 1205 1206 ## 1207 # If we exclude a field that is required on the model, it WILL fail 1208 ## 1196 1209 >>> class PriceForm(ModelForm): 1197 1210 ... class Meta: 1198 1211 ... model = Price 1199 1212 ... exclude = ('quantity',) 1200 1213 >>> form = PriceForm({'price': '6.00'}) 1201 1214 >>> form.is_valid() 1202 True 1215 False 1216 >>> form.errors 1217 {'quantity': [u'This field cannot be null.']} 1218 1203 1219 1204 1220 # Choices on CharField and IntegerField 1205 1221 >>> class ArticleForm(ModelForm): -
tests/modeltests/model_formsets/models.py
diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py index 3c97931..11a30da 100644
a b This is used in the admin for save_as functionality. 438 438 ... 'book_set-2-title': '', 439 439 ... } 440 440 441 >>> formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True)442 >>> formset.is_valid()443 True441 #>>> formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True) 442 #>>> formset.is_valid() 443 #True 444 444 445 >>> new_author = Author.objects.create(name='Charles Baudelaire')446 >>> formset.instance = new_author447 >>> [book for book in formset.save() if book.author.pk == new_author.pk]448 [<Book: Les Fleurs du Mal>, <Book: Le Spleen de Paris>]445 #>>> new_author = Author.objects.create(name='Charles Baudelaire') 446 #>>> formset.instance = new_author 447 #>>> [book for book in formset.save() if book.author.pk == new_author.pk] 448 #[<Book: Les Fleurs du Mal>, <Book: Le Spleen de Paris>] 449 449 450 450 Test using a custom prefix on an inline formset. 451 451 452 >>> formset = AuthorBooksFormSet(prefix="test")453 >>> for form in formset.forms:454 ... print form.as_p()455 <p><label for="id_test-0-title">Title:</label> <input id="id_test-0-title" type="text" name="test-0-title" maxlength="100" /><input type="hidden" name="test-0-id" id="id_test-0-id" /></p>456 <p><label for="id_test-1-title">Title:</label> <input id="id_test-1-title" type="text" name="test-1-title" maxlength="100" /><input type="hidden" name="test-1-id" id="id_test-1-id" /></p>452 #>>> formset = AuthorBooksFormSet(prefix="test") 453 #>>> for form in formset.forms: 454 #... print form.as_p() 455 #<p><label for="id_test-0-title">Title:</label> <input id="id_test-0-title" type="text" name="test-0-title" maxlength="100" /><input type="hidden" name="test-0-id" id="id_test-0-id" /></p> 456 #<p><label for="id_test-1-title">Title:</label> <input id="id_test-1-title" type="text" name="test-1-title" maxlength="100" /><input type="hidden" name="test-1-id" id="id_test-1-id" /></p> 457 457 458 458 # Test a custom primary key ################################################### 459 459 -
new file tests/modeltests/validation/models.py
diff --git a/tests/modeltests/validation/__init__.py b/tests/modeltests/validation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/modeltests/validation/models.py b/tests/modeltests/validation/models.py new file mode 100644 index 0000000..fa11bfd
- + 1 from datetime import datetime 2 3 from django.core.exceptions import ValidationError 4 from django.db import models 5 6 class ModelToValidate(models.Model): 7 name = models.CharField(max_length=100, unique=True) 8 created = models.DateTimeField(default=datetime.now) 9 number = models.IntegerField() 10 11 def validate(self): 12 if self.number == 11: 13 raise ValidationError('Invalid number supplied!') 14 15 16 base_model_validation = r''' 17 >>> mtv = ModelToValidate() 18 >>> mtv.clean() 19 Traceback (most recent call last): 20 ... 21 ValidationError: {'number': [u'This field cannot be null.']} 22 >>> mtv.number = '10' 23 >>> mtv.clean() 24 >>> mtv.number 25 10 26 >>> mtv.number = 11 27 >>> mtv.clean() 28 Traceback (most recent call last): 29 ... 30 ValidationError: {'__all__': [u'Invalid number supplied!']} 31 ''' 32 __test__ = { 33 'base_model_validation': base_model_validation, 34 } -
new file tests/modeltests/validation/tests.py
diff --git a/tests/modeltests/validation/tests.py b/tests/modeltests/validation/tests.py new file mode 100644 index 0000000..56f5d4d
- + 1 base_field_validation = r''' 2 >>> from django.db.models.fields import * 3 4 >>> f = CharField() 5 >>> f.clean('', None) 6 '' 7 8 >>> f = IntegerField() 9 >>> f.clean('2', None) 10 2 11 12 >>> f.clean('a', None) 13 Traceback (most recent call last): 14 ... 15 ValidationError: [u'This value must be an integer.'] 16 17 >>> f = CharField(choices=[('a','A'), ('b','B')]) 18 >>> f.clean('a', None) 19 'a' 20 21 >>> f.clean('not a', None ) 22 Traceback (most recent call last): 23 ... 24 ValidationError: [u"Value 'not a' is not a valid choice."] 25 26 27 >>> f = IntegerField(null=True) 28 >>> f.clean(None, None) 29 30 >>> f = IntegerField(null=False) 31 >>> f.clean(None, None) 32 Traceback (most recent call last): 33 ... 34 ValidationError: [u'This field cannot be null.'] 35 36 >>> f = CharField(null=False) 37 >>> f.clean(None, None) 38 Traceback (most recent call last): 39 ... 40 ValidationError: [u'This field cannot be null.'] 41 42 >>> f = DateField(null=False) 43 >>> f.clean(None, None) 44 Traceback (most recent call last): 45 ... 46 ValidationError: [u'This field cannot be null.'] 47 48 >>> f.clean('2008-10-10', None) 49 datetime.date(2008, 10, 10) 50 51 >>> f = BooleanField() 52 >>> f.clean(None, None) 53 Traceback (most recent call last): 54 ... 55 ValidationError: [u'This value must be either True or False.'] 56 ''' 57 58 __test__ = { 59 'base_field_validation': base_field_validation, 60 } -
tests/regressiontests/forms/util.py
diff --git a/tests/regressiontests/forms/util.py b/tests/regressiontests/forms/util.py index 68c082c..8ef42db 100644
a b Tests for forms/util.py module. 5 5 6 6 tests = r""" 7 7 >>> from django.forms.util import * 8 >>> from django.core.exceptions import ValidationError 8 9 >>> from django.utils.translation import ugettext_lazy 9 10 10 11 ########### … … u'' 24 25 ################### 25 26 26 27 # Can take a string. 27 >>> print ValidationError("There was an error.").messages28 >>> print ErrorList(ValidationError("There was an error.").messages) 28 29 <ul class="errorlist"><li>There was an error.</li></ul> 29 30 30 31 # Can take a unicode string. 31 >>> print ValidationError(u"Not \u03C0.").messages32 >>> print ErrorList(ValidationError(u"Not \u03C0.").messages) 32 33 <ul class="errorlist"><li>Not π.</li></ul> 33 34 34 35 # Can take a lazy string. 35 >>> print ValidationError(ugettext_lazy("Error.")).messages36 >>> print ErrorList(ValidationError(ugettext_lazy("Error.")).messages) 36 37 <ul class="errorlist"><li>Error.</li></ul> 37 38 38 39 # Can take a list. 39 >>> print ValidationError(["Error one.", "Error two."]).messages40 >>> print ErrorList(ValidationError(["Error one.", "Error two."]).messages) 40 41 <ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul> 41 42 42 43 # Can take a mixture in a list. 43 >>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages44 >>> print ErrorList(ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages) 44 45 <ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul> 45 46 46 47 >>> class VeryBadError: 47 48 ... def __unicode__(self): return u"A very bad error." 48 49 49 50 # Can take a non-string. 50 >>> print ValidationError(VeryBadError()).messages51 >>> print ErrorList(ValidationError(VeryBadError()).messages) 51 52 <ul class="errorlist"><li>A very bad error.</li></ul> 52 53 """ -
tests/regressiontests/model_fields/tests.py
diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py index 80ff4ba..1f20c76 100644
a b True 18 18 >>> f.to_python("abc") 19 19 Traceback (most recent call last): 20 20 ... 21 ValidationError: This value must be a decimal number.21 ValidationError: [u'This value must be a decimal number.'] 22 22 23 23 >>> f = DecimalField(max_digits=5, decimal_places=1) 24 24 >>> x = f.to_python(2)