Ticket #5150: unique.diff

File unique.diff, 3.4 KB (added by ctdecci@…, 17 years ago)
  • django/newforms/models.py

     
    33and database field objects.
    44"""
    55
     6from django.utils.text import capfirst
    67from django.utils.translation import ugettext
    78from django.utils.encoding import smart_unicode
    89
     
    6667        return save_instance(self, instance, fields, fail_message, commit)
    6768    return save
    6869
     70def make_unique_check(field, form, pk_val=None):
     71    "Returns a clean_%s() method for a Form."
     72    def check_unique(self):
     73        # if parent class also has clean_ method, then call it
     74        parent = super(form, self)
     75        if hasattr(parent, 'clean_%s' % field.name):
     76            value = getattr(parent, 'clean_%s' % field.name)()
     77        else:
     78            value = self.cleaned_data[field.name]
     79        queryset = self._model.objects.filter(**{field.name: value})
     80        if pk_val is not None:
     81            queryset = queryset.exclude(pk=pk_val)
     82        if queryset.count() > 0:
     83            raise ValidationError(ugettext(u'%s with this %s already exists.') % (capfirst(self._model._meta.verbose_name), field.verbose_name))
     84        return value
     85    return check_unique
     86
    6987def form_for_model(model, form=BaseForm, fields=None, formfield_callback=lambda f: f.formfield()):
    7088    """
    7189    Returns a Form class for the given Django model class.
     
    7896    """
    7997    opts = model._meta
    8098    field_list = []
     99    clean_methods = {}
    81100    for f in opts.fields + opts.many_to_many:
    82101        if not f.editable:
    83102            continue
    84103        if fields and not f.name in fields:
    85104            continue
    86         formfield = formfield_callback(f)
     105        formfield = formfield_callback(f, initial=f.get_default())
    87106        if formfield:
    88107            field_list.append((f.name, formfield))
     108            if f.unique:
     109                clean_methods['clean_%s' % f.name] = make_unique_check(f, form)
    89110    base_fields = SortedDictFromList(field_list)
    90111    return type(opts.object_name + 'Form', (form,),
    91         {'base_fields': base_fields, '_model': model, 'save': make_model_save(model, fields, 'created')})
     112        dict({'base_fields': base_fields, '_model': model, 'save': make_model_save(model, fields, 'created')}, **clean_methods))
    92113
    93114def form_for_instance(instance, form=BaseForm, fields=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
    94115    """
     
    104125    model = instance.__class__
    105126    opts = model._meta
    106127    field_list = []
     128    clean_methods = {}
    107129    for f in opts.fields + opts.many_to_many:
    108130        if not f.editable:
    109131            continue
     
    113135        formfield = formfield_callback(f, initial=current_value)
    114136        if formfield:
    115137            field_list.append((f.name, formfield))
     138            if f.unique:
     139                clean_methods['clean_%s' % f.name] = make_unique_check(f, form, instance._get_pk_val())
    116140    base_fields = SortedDictFromList(field_list)
    117141    return type(opts.object_name + 'InstanceForm', (form,),
    118         {'base_fields': base_fields, '_model': model, 'save': make_instance_save(instance, fields, 'changed')})
     142        dict({'base_fields': base_fields, '_model': model, 'save': make_instance_save(instance, fields, 'changed')}, **clean_methods))
    119143
    120144def form_for_fields(field_list):
    121145    "Returns a Form class for the given list of Django database field instances."
Back to Top