Code

Ticket #3232: apply_changes.patch

File apply_changes.patch, 4.5 KB (added by SmileyChris, 7 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)