Reputation: 1991
The following code successfully adds a new ToolCalibration to my database, however it does not save the SerialFormset or PartFormset. I've been staring at this code trying to figure it out for quite some time now, so any and all help would be greatly appreciated. Thanks!
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from tool_cal.models import ToolCalibration, SerialNumber, PartNumber
class ToolForm(ModelForm):
class Meta:
model = ToolCalibration
SerialFormSet = inlineformset_factory(ToolCalibration, SerialNumber, can_delete=True)
PartFormSet = inlineformset_factory(ToolCalibration, PartNumber, can_delete=True)
class ToolCreate(CreateView):
model = ToolCalibration
template_name = "create.html"
form_class = ToolForm
success_url = '/toolcal/success'
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates blank versions of the form
and its inline formsets.
"""
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
serial_form = SerialFormSet(prefix='serial')
part_form = PartFormSet(prefix='part')
return self.render_to_response(
self.get_context_data(form=form,
serial_form=serial_form,
part_form=part_form))
def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance and its inline
formsets with the passed POST variables and then checking them for
validity.
"""
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
serial_form = SerialFormSet(self.request.POST, prefix='serial')
part_form = PartFormSet(self.request.POST, prefix='part')
if (form.is_valid() and serial_form.is_valid() and
part_form.is_valid()):
return self.form_valid(form, serial_form, part_form)
else:
return self.form_invalid(form, serial_form, part_form)
def form_valid(self, form, serial_form, part_form):
"""
Called if all forms are valid. Creates a ToolCalibration instance along with
associated Serial and Parts and then redirects to a
success page.
"""
self.object = form.save()
serial_form.instance = self.object
serial_form.save()
part_form.instance = self.object
part_form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, serial_form, part_form):
"""
Called if a form is invalid. Re-renders the context data with the
data-filled forms and errors.
"""
return self.render_to_response(
self.get_context_data(form=form,
serial_form=serial_form,
part_form=part_form))
Upvotes: 0
Views: 358
Reputation: 8539
Have you considered using django-extra-views? It contains a quick and easy CBV for dealing with InlineFormSets.
In addition to an InlineFormSetView
and GenericInlineFormSetView
, they've also got a CreateWithInlinesView
that seems to be just what you want. Relevant docs here.
Example:
from extra_views import InlineFormSet, CreateWithInlinesView, UpdateWithInlinesView,
from extra_views.generic import GenericInlineFormSet
from tool_cal.models import ToolCalibration, SerialNumber, PartNumber
class SerialNumberInline(InlineFormSet):
model = SerialNumber
class PartNumberInline(GenericInlineFormSet):
model = PartNumber
class ToolCreateView(CreateWithInlinesView):
model = ToolCalibration
inlines = [SerialNumberInline, PartNumberInline]
def get_success_url(self):
return self.object.get_absolute_url()
Even if you don't want to use them, you could dig through the code and see how they handle it.
Upvotes: 1