Django

Code

Changeset 9239

Show
Ignore:
Timestamp:
10/21/08 09:04:24 (3 months ago)
Author:
kmtracey
Message:

Fixed #9039 -- Don't perform unique checks on NULL values, since NULL != NULL in SQL.

Files:

Legend:

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

    r9208 r9239  
    217217        from django.db.models.fields import FieldDoesNotExist 
    218218 
    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. 
     219        # Gather a list of checks to perform. We only perform unique checks  
     220        # for fields present and not None in cleaned_data.  Since this is a  
     221        # ModelForm, some fields may have been excluded; we can't perform a unique  
     222        # check on a form that is missing fields involved in that check.  It also does 
     223        # not make sense to check data that didn't validate, and since NULL does not  
     224        # equal NULL in SQL we should not do any unique checking for NULL values. 
    222225        unique_checks = [] 
    223226        for check in self.instance._meta.unique_together[:]: 
    224             fields_on_form = [field for field in check if field in self.fields
     227            fields_on_form = [field for field in check if field in self.cleaned_data and not self.cleaned_data[field] is None
    225228            if len(fields_on_form) == len(check): 
    226229                unique_checks.append(check) 
     
    229232 
    230233        # 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
     234        # the list of checks. Again, skip empty fields and any that did not validate
    232235        for name, field in self.fields.items(): 
    233236            try: 
     
    236239                # This is an extra field that's not on the ModelForm, ignore it 
    237240                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: 
     241            if f.unique and name in self.cleaned_data and not self.cleaned_data[name] is None: 
    242242                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]] 
    246243 
    247244        bad_fields = set() 
  • django/trunk/tests/modeltests/model_forms/models.py

    r9226 r9239  
    146146   def __unicode__(self): 
    147147      return self.name 
    148        
     148 
     149class Book(models.Model): 
     150    title = models.CharField(max_length=40) 
     151    author = models.ForeignKey(Writer, blank=True, null=True) 
     152    special_id = models.IntegerField(blank=True, null=True, unique=True) 
     153     
     154    class Meta: 
     155        unique_together = ('title', 'author') 
     156 
    149157__test__ = {'API_TESTS': """ 
    150158>>> from django import forms 
     
    12021210True 
    12031211 
     1212# Unique & unique together with null values 
     1213>>> class BookForm(ModelForm):  
     1214...     class Meta:  
     1215...        model = Book 
     1216>>> w = Writer.objects.get(name='Mike Royko') 
     1217>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It', 'author' : w.pk}) 
     1218>>> form.is_valid() 
     1219True 
     1220>>> form.save() 
     1221<Book: Book object> 
     1222>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It', 'author' : w.pk}) 
     1223>>> form.is_valid() 
     1224False 
     1225>>> form._errors 
     1226{'__all__': [u'Book with this Title and Author already exists.']} 
     1227>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It'}) 
     1228>>> form.is_valid() 
     1229True 
     1230>>> form.save() 
     1231<Book: Book object> 
     1232>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It'}) 
     1233>>> form.is_valid() 
     1234True 
     1235>>> form.save() 
     1236<Book: Book object> 
     1237 
    12041238# Choices on CharField and IntegerField 
    12051239>>> class ArticleForm(ModelForm):