Reputation: 1387
I have got a CreateView for emergency lighting tests done on sites. It gets the site from the url so the user does not need to enter it into the form. The CreateView Also has a emergency lighting device formset to attach multiple devices to the main test. When I hit submit on the form i get
form_valid() takes exactly 2 arguments (3 given)
models.py
class Site(models.Model):
....
class EmergencyLighting(models.Model):
site = models.ForeignKey(Site)
class EmergencyLightingDevice(models.Model):
emergency_lighting = models.ForeignKey(EmergencyLighting)
views.py
class FormsetMixin(object):
object = None
def get(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
return self.render_to_response(self.get_context_data(form=form, formset=formset))
def post(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def get_formset_class(self):
return self.formset_class
def get_formset(self, formset_class):
return formset_class(**self.get_formset_kwargs())
def get_formset_kwargs(self):
kwargs = {
'instance': self.object
}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def form_valid(self, form, formset):
self.object = form.save()
formset.instance = self.object
formset.save()
return redirect('/sites/list')
def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
class EmergencyLightingCreate(FormsetMixin, CreateView):
template_name = 'emergency_lighting/emergencylighting_form.html'
model = EmergencyLighting
form_class = EmergencyLightingForm
formset_class = EmergencyLightingFormSet
def form_valid(self, form):
emergency_lighting = form.save(commit=False)
emergency_lighting.site_id = self.kwargs['site']
return super(EmergencyLightingCreate, self).form_valid(form)
forms.py
class EmergencyLightingForm(forms.ModelForm):
class Meta:
model = EmergencyLighting
exclude = ('creation', 'last_modified')
class EmergencyLightingDeviceForm(forms.ModelForm):
class Meta:
model = EmergencyLightingDevice
exclude = ('creation', 'last_modified')
EmergencyLightingFormSet = inlineformset_factory(EmergencyLighting, EmergencyLightingDevice,
extra=0, min_num=1, exclude=('creation', 'last_modified'))
urls.py
url(r'^(?P<site>[0-9]+)/create/$', EmergencyLightingCreate.as_view(), name='emergency-lighting-create'),
Upvotes: 0
Views: 946
Reputation: 599788
Like the error says, you're passing three arguments to form_valid
; that's because you explicitly overrode post
to send those three, and modified the signature of form_valid
in FormsetMixin to accept them. However in EmergencyLightingCreate you've reverted to only accepting two arguments. You need to be consistent about how many arguments your methods accept when you're subclassing.
Upvotes: 1