Django

Code

Changeset 4300

Show
Ignore:
Timestamp:
01/08/07 23:49:47 (2 years ago)
Author:
adrian
Message:

Fixed #3232 -- newforms: Added save_instance(), which saves a given bound form's clean_data into a given model instance with the same field names

Files:

Legend:

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

    r4299 r4300  
    66from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList 
    77 
    8 __all__ = ('form_for_model', 'form_for_instance', 'form_for_fields') 
     8__all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields') 
    99 
    1010def model_save(self, commit=True): 
     
    2121    return obj 
    2222 
    23 def make_instance_save(opts, instance): 
     23def save_instance(form, instance, commit=True): 
     24    """ 
     25    Saves bound Form ``form``'s clean_data into model instance ``instance``. 
     26 
     27    Assumes ``form`` has a field for every non-AutoField database field in 
     28    ``instance``. If commit=True, then the changes to ``instance`` will be 
     29    saved to the database. Returns ``instance``. 
     30    """ 
     31    from django.db import models 
     32    opts = instance.__class__._meta 
     33    if form.errors: 
     34        raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name) 
     35    clean_data = form.clean_data 
     36    for f in opts.fields + opts.many_to_many: 
     37        if isinstance(f, models.AutoField): 
     38            continue 
     39        setattr(instance, f.attname, clean_data[f.name]) 
     40    if commit: 
     41        instance.save() 
     42    return instance 
     43 
     44def make_instance_save(instance): 
    2445    "Returns the save() method for a form_for_instance Form." 
    25     from django.db import models 
    26     def apply_changes(self, commit=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 commit: 
    35             instance.save() 
    36         return instance 
    37     return apply_changes 
     46    def save(self, commit=True): 
     47        return save_instance(self, instance, commit) 
     48    return save 
    3849 
    3950def form_for_model(model, form=BaseForm): 
     
    4152    Returns a Form class for the given Django model class. 
    4253 
    43     Provide 'form' if you want to use a custom BaseForm subclass. 
     54    Provide ``form`` if you want to use a custom BaseForm subclass. 
    4455    """ 
    4556    opts = model._meta 
     
    5667    Returns a Form class for the given Django model instance. 
    5768 
    58     Provide 'form' if you want to use a custom BaseForm subclass. 
     69    Provide ``form`` if you want to use a custom BaseForm subclass. 
    5970    """ 
    6071    model = instance.__class__ 
     
    6879    fields = SortedDictFromList(field_list) 
    6980    return type(opts.object_name + 'InstanceForm', (form,), 
    70         {'fields': fields, '_model': model, 'save': make_instance_save(opts, instance)}) 
     81        {'fields': fields, '_model': model, 'save': make_instance_save(instance)}) 
    7182 
    7283def form_for_fields(field_list): 
  • django/trunk/tests/modeltests/model_forms/models.py

    r4299 r4300  
    1616returns a Form that is tied to the instance. This form works just like any 
    1717other Form, with one additional method: save(). The save() 
    18 method updates the model instance. It saves the changes to the database if 
    19 save(commit=True), which is default. If you pass commit=False, then you'll 
    20 get the object without committing the changes to the database. 
     18method updates the model instance. It also takes a commit=True parameter. 
     19 
     20The function django.newforms.save_instance() takes a bound form instance and a 
     21model instance and saves the form's clean_data into the instance. It also takes 
     22a commit=True parameter. 
    2123""" 
    2224 
     
    4648 
    4749__test__ = {'API_TESTS': """ 
    48 >>> from django.newforms import form_for_model, form_for_instance, BaseForm 
     50>>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField 
    4951>>> import datetime 
    5052 
     
    219221</select></li> 
    220222 
     223Here, we define a custom Form. Because it happens to have the same fields as 
     224the Category model, we can use save_instance() to apply its changes to an 
     225existing Category instance. 
     226>>> class ShortCategory(Form): 
     227...     name = CharField(max_length=5) 
     228...     url = CharField(max_length=3) 
     229>>> cat = Category.objects.get(name='Third test') 
     230>>> cat 
     231<Category: Third test> 
     232>>> cat.id 
     2333 
     234>>> sc = ShortCategory({'name': 'Third', 'url': '3rd'}) 
     235>>> save_instance(sc, cat) 
     236<Category: Third> 
     237>>> Category.objects.get(id=3) 
     238<Category: Third> 
    221239"""}