Django

Code

Ticket #6845: 6845-against-9226.diff

File 6845-against-9226.diff, 37.2 kB (added by Honza_Kral, 1 year ago)
  • a/django/contrib/contenttypes/generic.py

    old new  
    313313            self.ct_fk_field.name: self.instance.pk, 
    314314        }) 
    315315 
    316     def save_new(self, form, commit=True): 
     316    def _construct_form(self, i, **kwargs): 
    317317        # Avoid a circular import. 
    318318        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): 
    323332        new_obj = self.model(**kwargs) 
    324333        return save_instance(form, new_obj, commit=commit) 
    325334 
  • a/django/contrib/localflavor/au/forms.py

    old new  
    44 
    55from django.forms import ValidationError 
    66from django.forms.fields import Field, RegexField, Select, EMPTY_VALUES 
    7 from django.forms.util import smart_unicode 
     7from django.utils.encoding import smart_unicode 
    88from django.utils.translation import ugettext_lazy as _ 
    99import re 
    1010 
  • a/django/contrib/localflavor/ca/forms.py

    old new  
    44 
    55from django.forms import ValidationError 
    66from django.forms.fields import Field, RegexField, Select, EMPTY_VALUES 
    7 from django.forms.util import smart_unicode 
     7from django.utils.encoding import smart_unicode 
    88from django.utils.translation import ugettext_lazy as _ 
    99import re 
    1010 
  • a/django/core/exceptions.py

    old new  
    3232    """Some kind of problem with a model field.""" 
    3333    pass 
    3434 
     35NON_FIELD_ERRORS = '__all__' 
    3536class ValidationError(Exception): 
    3637    """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) 
  • a/django/db/models/base.py

    old new  
    99    from sets import Set as set     # Python 2.3 fallback. 
    1010 
    1111import django.db.models.manager     # Imported to register signal handler. 
    12 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError 
     12from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS 
    1313from django.db.models.fields import AutoField 
    1414from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 
    1515from django.db.models.query import delete_objects, Q, CollectedObjects 
     
    1919from django.db.models.loading import register_models, get_model 
    2020from django.utils.functional import curry 
    2121from django.utils.encoding import smart_str, force_unicode, smart_unicode 
     22from django.utils.text import get_text_list, capfirst 
     23from django.utils.translation import ugettext_lazy as _ 
    2224from django.conf import settings 
    2325 
    2426 
     
    477479            setattr(self, cachename, obj) 
    478480        return getattr(self, cachename) 
    479481 
     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 
    480581 
    481582 
    482583############################################ 
  • a/django/db/models/fields/__init__.py

    old new  
    117117        Returns the converted value. Subclasses should override this. 
    118118        """ 
    119119        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 
    120146 
    121147    def db_type(self): 
    122148        """ 
     
    346372        except (TypeError, ValueError): 
    347373            raise exceptions.ValidationError( 
    348374                _("This value must be an integer.")) 
     375         
     376    def validate(self, value, model_instance): 
     377        pass 
    349378 
    350379    def get_db_prep_value(self, value): 
    351380        if value is None: 
     
    402431        return "CharField" 
    403432 
    404433    def to_python(self, value): 
    405         if isinstance(value, basestring)
     434        if isinstance(value, basestring) or value is None
    406435            return value 
    407         if value is None: 
    408             if self.null: 
    409                 return value 
    410             else: 
    411                 raise exceptions.ValidationError( 
    412                     ugettext_lazy("This field cannot be null.")) 
    413436        return smart_unicode(value) 
    414437 
    415438    def formfield(self, **kwargs): 
  • a/django/db/models/fields/related.py

    old new  
    645645 
    646646        self.db_index = True 
    647647 
     648    def validate(self, value, model_instance): 
     649        if self.rel.parent_link: 
     650            return 
     651        super(ForeignKey, self).validate(value, model_instance) 
     652 
    648653    def get_attname(self): 
    649654        return '%s_id' % self.name 
    650655 
     
    735740            return None 
    736741        return super(OneToOneField, self).formfield(**kwargs) 
    737742 
     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 
    738751class ManyToManyField(RelatedField, Field): 
    739752    def __init__(self, to, **kwargs): 
    740753        try: 
  • a/django/forms/__init__.py

    old new  
    1010    "This form field requires foo.js" and form.js_includes() 
    1111""" 
    1212 
    13 from util import ValidationError 
     13from django.core.exceptions import ValidationError 
    1414from widgets import * 
    1515from fields import * 
    1616from forms import * 
  • a/django/forms/fields.py

    old new  
    2323except NameError: 
    2424    from sets import Set as set 
    2525 
    26 import django.core.exceptions 
     26from django.core.exceptions import ValidationError 
    2727from django.utils.translation import ugettext_lazy as _ 
    2828from django.utils.encoding import smart_unicode, smart_str 
    2929 
    30 from util import ErrorList, ValidationError 
     30from util import ErrorList  
    3131from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, SplitHiddenDateTimeWidget 
    3232from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile 
    3333 
     
    677677        if value == self.empty_value or value in EMPTY_VALUES: 
    678678            return self.empty_value 
    679679         
    680         # Hack alert: This field is purpose-made to use with Field.to_python as 
    681         # 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 than 
    684         # django.forms.utils.ValidationError. So unfortunatly we need to catch 
    685         # both. 
    686680        try: 
    687681            value = self.coerce(value) 
    688         except (ValueError, TypeError, django.core.exceptions.ValidationError): 
     682        except (ValueError, TypeError, ValidationError): 
    689683            raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) 
    690684        return value 
    691685 
  • a/django/forms/forms.py

    old new  
    44 
    55from copy import deepcopy 
    66 
     7from django.core.exceptions import ValidationError 
    78from django.utils.datastructures import SortedDict 
    89from django.utils.html import escape 
    910from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode 
     
    1112 
    1213from fields import Field, FileField 
    1314from widgets import Media, media_property, TextInput, Textarea 
    14 from util import flatatt, ErrorDict, ErrorList, ValidationError 
     15from util import flatatt, ErrorDict, ErrorList 
    1516 
    1617__all__ = ('BaseForm', 'Form') 
    1718 
     
    234235                    value = getattr(self, 'clean_%s' % name)() 
    235236                    self.cleaned_data[name] = value 
    236237            except ValidationError, e: 
    237                 self._errors[name] = e.messages 
     238                self._errors[name] = self.error_class(e.messages) 
    238239                if name in self.cleaned_data: 
    239240                    del self.cleaned_data[name] 
    240241        try: 
    241242            self.cleaned_data = self.clean() 
    242243        except ValidationError, e: 
    243             self._errors[NON_FIELD_ERRORS] = e.messages 
     244            self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages) 
    244245        if self._errors: 
    245246            delattr(self, 'cleaned_data') 
    246247 
  • a/django/forms/formsets.py

    old new  
    11from forms import Form 
     2from django.core.exceptions import ValidationError 
    23from django.utils.encoding import StrAndUnicode 
    34from django.utils.safestring import mark_safe 
    45from django.utils.translation import ugettext as _ 
    56from fields import IntegerField, BooleanField 
    67from widgets import Media, HiddenInput 
    7 from util import ErrorList, ValidationError 
     8from util import ErrorList 
    89 
    910__all__ = ('BaseFormSet', 'all_valid') 
    1011 
  • a/django/forms/models.py

    old new  
    55 
    66from django.utils.encoding import smart_unicode 
    77from django.utils.datastructures import SortedDict 
    8 from django.utils.text import get_text_list, capfirst 
    98from django.utils.translation import ugettext_lazy as _ 
    109 
    11 from util import ValidationError, ErrorList 
     10from django.core.exceptions import ValidationError, NON_FIELD_ERRORS 
     11from util import ErrorList 
    1212from forms import BaseForm, get_declared_fields 
    1313from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES 
    1414from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput 
     
    2626    'ModelMultipleChoiceField', 
    2727) 
    2828 
    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     """ 
     29def make_instance(form, instance, fields=None, exclude=None): 
    3830    from django.db import models 
    3931    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 
    4333    cleaned_data = form.cleaned_data 
    4434    for f in opts.fields: 
    4535        if not f.editable or isinstance(f, models.AutoField) \ 
     
    4939            continue 
    5040        if exclude and f.name in exclude: 
    5141            continue 
     42        if getattr(f.rel, 'parent_link', False) and not cleaned_data[f.name]: 
     43            continue 
    5244        f.save_form_data(instance, cleaned_data[f.name]) 
     45    return instance 
     46 
     47def 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)) 
    5352    # Wrap up the saving of m2m data as a function. 
    5453    def save_m2m(): 
    5554        opts = instance._meta 
     
    6968        form.save_m2m = save_m2m 
    7069    return instance 
    7170 
     71 
     72def 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 
    7283def make_model_save(model, fields, fail_message): 
    7384    """Returns the save() method for a Form.""" 
    7485    def save(self, commit=True): 
     
    210221        super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data, 
    211222                                            error_class, label_suffix, empty_permitted) 
    212223    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             
    214240        return self.cleaned_data 
    215241 
    216     def validate_unique(self): 
    217         from django.db.models.fields import FieldDoesNotExist 
    218  
    219         # Gather a list of checks to perform. Since this is a ModelForm, some 
    220         # fields may have been excluded; we can't perform a unique check on a 
    221         # 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 to 
    231         # 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 it 
    237                 continue 
    238             # MySQL can't handle ... WHERE pk IS NULL, so make sure we 
    239             # don't generate queries of that form. 
    240             is_null_pk = f.primary_key and self.cleaned_data[name] is None 
    241             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 this 
    250             # 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 an 
    259             # 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 to 
    264             # 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 field 
    269                 if len(unique_check) == 1: 
    270                     field_name = unique_check[0] 
    271                     field_label = self.fields[field_name].label 
    272                     # Insert the error into the error dict, very sneaky 
    273                     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_together 
    279                 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 data 
    289                 # 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 considered 
    297             # form-wide. 
    298             raise ValidationError(form_errors) 
    299  
    300242    def save(self, commit=True): 
    301243        """ 
    302244        Saves this ``form``'s cleaned_data into model instance 
     
    309251            fail_message = 'created' 
    310252        else: 
    311253            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) 
    313256 
    314257class ModelForm(BaseModelForm): 
    315258    __metaclass__ = ModelFormMetaclass 
     
    363306 
    364307    def save_new(self, form, commit=True): 
    365308        """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) 
    367310 
    368311    def save_existing(self, form, instance, commit=True): 
    369312        """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) 
    371314 
    372315    def save(self, commit=True): 
    373316        """Saves model instances for every form, adding and changing instances 
     
    467410            # Remove the primary key from the form's data, we are only 
    468411            # creating new instances 
    469412            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) 
    470415        return form 
    471416 
    472417    def get_queryset(self): 
     
    477422        kwargs = {self.fk.name: self.instance} 
    478423        return self.model._default_manager.filter(**kwargs) 
    479424 
    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  
    485425    def add_fields(self, form, index): 
    486426        super(BaseInlineFormSet, self).add_fields(form, index) 
    487427        if self._pk_field == self.fk: 
  • a/django/forms/util.py

    old new  
    11from django.utils.html import conditional_escape 
    2 from django.utils.encoding import smart_unicode, StrAndUnicode, force_unicode 
     2from django.utils.encoding import StrAndUnicode, force_unicode 
    33from django.utils.safestring import mark_safe 
    44 
    55def flatatt(attrs): 
     
    4848    def __repr__(self): 
    4949        return repr([force_unicode(e) for e in self]) 
    5050 
    51 class ValidationError(Exception): 
    52     def __init__(self, message): 
    53         """ 
    54         ValidationError can be passed any object that can be printed (usually 
    55         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 exception 
    65         # instance would result in this: 
    66         # AttributeError: ValidationError instance has no attribute 'args' 
    67         # See http://www.python.org/doc/current/tut/node10.html#handling 
    68         return repr(self.messages) 
  • a/tests/modeltests/model_forms/models.py

    old new  
    7474    article = models.OneToOneField(Article, parent_link=True) 
    7575 
    7676class BetterWriter(Writer): 
    77     pass 
     77    score = models.IntegerField() 
    7878 
    7979class WriterProfile(models.Model): 
    8080    writer = models.OneToOneField(Writer, primary_key=True) 
     
    850850>>> ImprovedArticleWithParentLinkForm.base_fields.keys() 
    851851[] 
    852852 
    853 >>> bw = BetterWriter(name=u'Joe Better'
     853>>> bw = BetterWriter(name=u'Joe Better', score=10
    854854>>> bw.save() 
    855855>>> 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() 
     863True 
     864>>> bw2 = form.save() 
     865>>> bw2.delete() 
     866 
    857867 
    858868>>> class WriterProfileForm(ModelForm): 
    859869...     class Meta: 
     
    11931203>>> form._errors 
    11941204{'__all__': [u'Price with this Price and Quantity already exists.']} 
    11951205 
     1206## 
     1207# If we exclude a field that is required on the model, it WILL fail 
     1208## 
    11961209>>> class PriceForm(ModelForm): 
    11971210...     class Meta: 
    11981211...         model = Price 
    11991212...         exclude = ('quantity',) 
    12001213>>> form = PriceForm({'price': '6.00'}) 
    12011214>>> form.is_valid() 
    1202 True 
     1215False 
     1216>>> form.errors 
     1217{'quantity': [u'This field cannot be null.']} 
     1218 
    12031219 
    12041220# Choices on CharField and IntegerField 
    12051221>>> class ArticleForm(ModelForm): 
  • a/tests/modeltests/model_formsets/models.py

    old new  
    438438...     'book_set-2-title': '', 
    439439... } 
    440440 
    441 >>> formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True) 
    442 >>> formset.is_valid() 
    443 True 
     441#>>> formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True) 
     442#>>> formset.is_valid() 
     443#True 
    444444 
    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>] 
     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>] 
    449449 
    450450Test using a custom prefix on an inline formset. 
    451451 
    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> 
    457457 
    458458# Test a custom primary key ################################################### 
    459459 
  • /dev/null

    old new  
     1from datetime import datetime 
     2 
     3from django.core.exceptions import ValidationError 
     4from django.db import models 
     5 
     6class 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 
     16base_model_validation = r''' 
     17>>> mtv = ModelToValidate() 
     18>>> mtv.clean() 
     19Traceback (most recent call last): 
     20  ... 
     21ValidationError: {'number': [u'This field cannot be null.']} 
     22>>> mtv.number = '10' 
     23>>> mtv.clean() 
     24>>> mtv.number 
     2510 
     26>>> mtv.number = 11 
     27>>> mtv.clean() 
     28Traceback (most recent call last): 
     29  ... 
     30ValidationError: {'__all__': [u'Invalid number supplied!']} 
     31''' 
     32__test__ = { 
     33    'base_model_validation': base_model_validation, 
     34} 
  • /dev/null

    old new  
     1base_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) 
     102 
     11 
     12>>> f.clean('a', None) 
     13Traceback (most recent call last): 
     14  ... 
     15ValidationError: [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 ) 
     22Traceback (most recent call last): 
     23  ... 
     24ValidationError: [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) 
     32Traceback (most recent call last): 
     33  ... 
     34ValidationError: [u'This field cannot be null.'] 
     35 
     36>>> f = CharField(null=False) 
     37>>> f.clean(None, None) 
     38Traceback (most recent call last): 
     39  ... 
     40ValidationError: [u'This field cannot be null.'] 
     41 
     42>>> f = DateField(null=False) 
     43>>> f.clean(None, None) 
     44Traceback (most recent call last): 
     45  ... 
     46ValidationError: [u'This field cannot be null.'] 
     47 
     48>>> f.clean('2008-10-10', None) 
     49datetime.date(2008, 10, 10) 
     50 
     51>>> f = BooleanField() 
     52>>> f.clean(None, None) 
     53Traceback (most recent call last): 
     54  ... 
     55ValidationError: [u'This value must be either True or False.'] 
     56''' 
     57 
     58__test__ = { 
     59    'base_field_validation': base_field_validation, 
     60} 
  • a/tests/regressiontests/forms/util.py

    old new  
    55 
    66tests = r""" 
    77>>> from django.forms.util import * 
     8>>> from django.core.exceptions import ValidationError 
    89>>> from django.utils.translation import ugettext_lazy 
    910 
    1011########### 
     
    2425################### 
    2526 
    2627# Can take a string. 
    27 >>> print ValidationError("There was an error.").messages 
     28>>> print ErrorList(ValidationError("There was an error.").messages) 
    2829<ul class="errorlist"><li>There was an error.</li></ul> 
    2930 
    3031# Can take a unicode string. 
    31 >>> print ValidationError(u"Not \u03C0.").messages 
     32>>> print ErrorList(ValidationError(u"Not \u03C0.").messages) 
    3233<ul class="errorlist"><li>Not π.</li></ul> 
    3334 
    3435# Can take a lazy string. 
    35 >>> print ValidationError(ugettext_lazy("Error.")).messages 
     36>>> print ErrorList(ValidationError(ugettext_lazy("Error.")).messages) 
    3637<ul class="errorlist"><li>Error.</li></ul> 
    3738 
    3839# Can take a list. 
    39 >>> print ValidationError(["Error one.", "Error two."]).messages 
     40>>> print ErrorList(ValidationError(["Error one.", "Error two."]).messages) 
    4041<ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul> 
    4142 
    4243# Can take a mixture in a list. 
    43 >>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages 
     44>>> print ErrorList(ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages) 
    4445<ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul> 
    4546 
    4647>>> class VeryBadError: 
    4748...     def __unicode__(self): return u"A very bad error." 
    4849 
    4950# Can take a non-string. 
    50 >>> print ValidationError(VeryBadError()).messages 
     51>>> print ErrorList(ValidationError(VeryBadError()).messages) 
    5152<ul class="errorlist"><li>A very bad error.</li></ul> 
    5253""" 
  • a/tests/regressiontests/model_fields/tests.py

    old new  
    1818>>> f.to_python("abc") 
    1919Traceback (most recent call last): 
    2020... 
    21 ValidationError: This value must be a decimal number. 
     21ValidationError: [u'This value must be a decimal number.'] 
    2222 
    2323>>> f = DecimalField(max_digits=5, decimal_places=1) 
    2424>>> x = f.to_python(2)