Monday, April 22, 2013

Multi-Object-Edit with formsets by Kaula

A Germanian developer named Christian Kaula wrote a great tutorial about manipulating multiple objects (forms) from Django formset here . But, as he mentioned in the article, the code was written from his memory, so It's buggy.

A couple days ago, I've just contacted him to ask about parts of the code I didn't understand. Luckily, he's replied and fixed the code. Thanks for that, I can apply his tutorial to my project without any doubts. 

I just want to take some notes here for future use.

- Your


# from django import forms from django.forms.models import modelformset_factory from fooproject.models import Foo # creating a FormSet for a specific Model is easy FooFormSetBase = modelformset_factory( Foo, extra=0, fields=('somefield', 'someotherfield'))  # now we want to add a checkbox so we can do stuff to only selected items class FooFormSet(FooFormSetBase): # this is where you can add additional fields to a ModelFormSet # this is also where you can change stuff about the auto generated form def add_fields(self, form, index): super(FooFormSet, self).add_fields(form, index) form.fields['is_checked'] = forms.BooleanField(required=False) form.fields['somefield'].widget.attrs['class'] = 'somefieldclass'



# from django.shortcuts import redirect, render_to_response from django.template import RequestContext from fooproject.fooapp.forms import FooFormSet from fooproject.models import Foo  def fooview(request): if request.method == 'POST': # we have multiple actions - save and delete in this case action = request.POST.get('action') formset = FooFormSet( request.POST, queryset=Foo.objects.all())  if formset.is_valid(): # iterate over all forms in the formset for form in formset.forms: # only do stuff for forms in which is_checked is checked if form.cleaned_data.get('is_checked'): if action == u'delete': # we need to call save to get an actual model but # there is no need to hit the database hence the # commit=False model_instance = # now that we got a model we can delete it model_instance.delete() if action == u'save':  return redirect('someview') # !!!  else: formset = FooFormSet(queryset=Foo.objects.all())  return render_to_response('sometemplate.html', {'formset': formset}, context_instance=RequestContext(request))

- Your template


<form action="." method="post" accept-charset="utf-8"> <table> <thead> <tr> <th>is_checked</th> <th>somefield</th> <th>someotherfield</th> </tr> </thead> <tbody> {% for form in formset.forms %} <tr> <td> {# don't forget about the id field #} {{ }} {{ form.is_checked }} </td> <td>{{ form.somefield }}</td> <td>{{ form.someotherfield }}</td> </tr> {% endfor %} </tbody> </table> <p> {# and don't forget about the management form #} {{ formset.management_form }} {% csrf_token %} <button type="submit" name="action" value="save">save</button> <button type="submit" name="action" value="delete">delete</button> </p> </form>