Ticket #4001: 4001.diff

File 4001.diff, 2.5 KB (added by Russell Keith-Magee, 12 years ago)

Method to add deferred m2m save method to form if commit=False

  • django/newforms/models.py

     
    3535        if fields and f.name not in fields:
    3636            continue
    3737        setattr(instance, f.name, cleaned_data[f.name])
    38     if commit:
    39         instance.save()
     38    # Wrap up the saving of m2m data as a function
     39    def save_m2m():
     40        opts = instance.__class__._meta
     41        cleaned_data = form.cleaned_data
    4042        for f in opts.many_to_many:
    4143            if fields and f.name not in fields:
    4244                continue
    4345            if f.name in cleaned_data:
    4446                setattr(instance, f.attname, cleaned_data[f.name])
    45     # GOTCHA: If many-to-many data is given and commit=False, the many-to-many
    46     # data will be lost. This happens because a many-to-many options cannot be
    47     # set on an object until after it's saved. Maybe we should raise an
    48     # exception in that case.
     47    if commit:
     48        # If we are committing, save the instance and the m2m data immediately
     49        instance.save()
     50        save_m2m()
     51    else:
     52        # We're not committing. Add a method to the form to allow deferred
     53        # saving of m2m data
     54        form.save_m2m = save_m2m
    4955    return instance
    5056
    5157def make_model_save(model, fields, fail_message):
  • tests/modeltests/model_forms/models.py

     
    332332>>> new_art.categories.all()
    333333[]
    334334
     335Create a new article, with categories, via the form, but use commit=False.
     336The m2m data won't be saved until save_m2m() is invoked on the form.
     337>>> ArticleForm = form_for_model(Article)
     338>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01',
     339...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
     340>>> new_art = f.save(commit=False)
     341
     342# Manually save the instance
     343>>> new_art.save()
     344>>> new_art.id
     3454
     346
     347# The instance doesn't have m2m data yet
     348>>> new_art = Article.objects.get(id=4)
     349>>> new_art.categories.all()
     350[]
     351
     352# Save the m2m data on the form
     353>>> f.save_m2m()
     354>>> new_art.categories.all()
     355[<Category: Entertainment>, <Category: It's a test>]
     356
    335357Here, we define a custom Form. Because it happens to have the same fields as
    336358the Category model, we can use save_instance() to apply its changes to an
    337359existing Category instance.
Back to Top