Django

Code

Changeset 9208

Show
Ignore:
Timestamp:
10/08/08 05:09:44 (3 months ago)
Author:
mtredinnick
Message:

Fixed #9319 -- Fixed a crash when using the same model field in multiple
unique_together constraints.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/forms/models.py

    r9086 r9208  
    1515from widgets import media_property 
    1616from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME 
     17 
     18try: 
     19    set 
     20except NameError: 
     21    from sets import Set as set     # Python 2.3 fallback 
    1722 
    1823__all__ = ( 
     
    220225            if len(fields_on_form) == len(check): 
    221226                unique_checks.append(check) 
    222              
     227 
    223228        form_errors = [] 
    224          
     229 
    225230        # Gather a list of checks for fields declared as unique and add them to 
    226231        # the list of checks. Again, skip fields not on the form. 
     
    236241            if name in self.cleaned_data and f.unique and not is_null_pk: 
    237242                unique_checks.append((name,)) 
    238                  
     243 
    239244        # Don't run unique checks on fields that already have an error. 
    240245        unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]] 
    241          
     246 
     247        bad_fields = set() 
    242248        for unique_check in unique_checks: 
    243249            # Try to look up an existing object with the same values as this 
    244250            # object's values for all the unique field. 
    245              
     251 
    246252            lookup_kwargs = {} 
    247253            for field_name in unique_check: 
    248254                lookup_kwargs[field_name] = self.cleaned_data[field_name] 
    249              
     255 
    250256            qs = self.instance.__class__._default_manager.filter(**lookup_kwargs) 
    251257 
    252             # Exclude the current object from the query if we are editing an  
     258            # Exclude the current object from the query if we are editing an 
    253259            # instance (as opposed to creating a new one) 
    254260            if self.instance.pk is not None: 
    255261                qs = qs.exclude(pk=self.instance.pk) 
    256                  
     262 
    257263            # This cute trick with extra/values is the most efficient way to 
    258264            # tell if a particular query returns any results. 
    259265            if qs.extra(select={'a': 1}).values('a').order_by(): 
    260266                model_name = capfirst(self.instance._meta.verbose_name) 
    261                  
     267 
    262268                # A unique field 
    263269                if len(unique_check) == 1: 
     
    279285                         'field_label': unicode(field_labels)} 
    280286                    ) 
    281                  
    282                 # Remove the data from the cleaned_data dict since it was invalid 
     287 
     288                # Mark these fields as needing to be removed from cleaned data 
     289                # later. 
    283290                for field_name in unique_check: 
    284                     del self.cleaned_data[field_name] 
    285          
     291                    bad_fields.add(field_name) 
     292 
     293        for field_name in bad_fields: 
     294            del self.cleaned_data[field_name] 
    286295        if form_errors: 
    287             # Raise the unique together errors since they are considered form-wide. 
     296            # Raise the unique together errors since they are considered 
     297            # form-wide. 
    288298            raise ValidationError(form_errors) 
    289299 
     
    472482        new_obj = self.model(**kwargs) 
    473483        return save_instance(form, new_obj, exclude=[self._pk_field.name], commit=commit) 
    474      
     484 
    475485    def add_fields(self, form, index): 
    476486        super(BaseInlineFormSet, self).add_fields(form, index)