Ticket #3232: apply_changes.patch

File apply_changes.patch, 4.5 KB (added by SmileyChris, 8 years ago)
  • django/newforms/forms.py

     
    171171        """
    172172        return self.clean_data
    173173
     174    def apply_changes(self, instance=None, save=True):
     175        if not instance:
     176            instance = getattr(self, 'default_instance', None)
     177            if not instance:
     178                raise ValueError('An instance is required')
     179        opts = instance._meta
     180        if self.errors:
     181            raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name)
     182        # Generate a list of db fields for this instance.
     183        db_fields = {}
     184        for db_field in opts.fields + opts.many_to_many:
     185            db_fields[db_field.attname] = db_field
     186        # Save each field in the form which matches a db field.
     187        for field in self.fields.keys():
     188            db_field = db_fields.get(field)
     189            setattr(instance, db_field.attname, self.clean_data[field])
     190        if save:
     191            instance.save()
     192        return instance
     193
    174194class Form(BaseForm):
    175195    "A collection of Fields, plus their associated data."
    176196    # This is a separate class from BaseForm in order to abstract the way
  • django/newforms/models.py

     
    2020        obj.save()
    2121    return obj
    2222
    23 def make_apply_changes(opts, instance):
    24     "Returns the apply_changes() method for a form_for_instance Form."
    25     from django.db import models
    26     def apply_changes(self, save=True):
    27         if self.errors:
    28             raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name)
    29         clean_data = self.clean_data
    30         for f in opts.fields + opts.many_to_many:
    31             if isinstance(f, models.AutoField):
    32                 continue
    33             setattr(instance, f.attname, clean_data[f.name])
    34         if save:
    35             instance.save()
    36         return instance
    37     return apply_changes
    38 
    3923def form_for_model(model, form=BaseForm):
    4024    """
    4125    Returns a Form class for the given Django model class.
     
    6751            field_list.append((f.name, formfield))
    6852    fields = SortedDictFromList(field_list)
    6953    return type(opts.object_name + 'InstanceForm', (form,),
    70         {'fields': fields, '_model': model, 'apply_changes': make_apply_changes(opts, instance)})
     54        {'fields': fields, '_model': model, 'default_instance': instance})
    7155
    7256def form_for_fields(field_list):
    7357    "Returns a Form class for the given list of Django database field instances."
  • tests/modeltests/model_forms/models.py

     
    1212create(save=False), then you'll get the object without saving it.
    1313
    1414The function django.newforms.form_for_instance() takes a model instance and
    15 returns a Form that is tied to the instance. This form works just like any
    16 other Form, with one additional method: apply_changes(). The apply_changes()
    17 method updates the model instance. It saves the changes to the database if
    18 apply_changes(save=True), which is default. If you pass save=False, then you'll
    19 get the object without saving it.
     15returns a Form that is tied to the instance.
     16
     17All forms now have the method apply_changes(instance), which can be used to
     18update a model instance. Using form_for_instance() you do not need to pass
     19an instance. It saves the changes to the database if apply_changes(save=True),
     20which is default. If you pass save=False, then the unsaved instance object
     21will be returned.
    2022"""
    2123
    2224from django.db import models
     
    153155>>> f.say_hello()
    154156hello
    155157
    156 Use form_for_instance to create a Form from a model instance. There are two
    157 differences between this Form and one created via form_for_model. First, the
    158 object's current values are inserted as 'initial' data in each Field. Second,
    159 the Form gets an apply_changes() method instead of a create() method.
     158Use form_for_instance to create a Form from a model instance. The difference
     159between this Form and a normal form is that the object's current values are
     160inserted as 'initial' data in each Field.
    160161>>> w = Writer.objects.get(name='Mike Royko')
    161162>>> RoykoForm = form_for_instance(w)
    162163>>> f = RoykoForm(auto_id=False)
Back to Top