Reputation: 439
class BaseContactPersonFormSet(forms.models.BaseModelFormSet):
def __init__(self, company, data=None, **kwargs):
super(BaseContactPersonFormSet, self).__init__(**kwargs)
for form in self:
form.company = company
ContactPersonFormSet = forms.models.modelformset_factory(model=Person, form=SingleContactPersonForm, formset=BaseContactPersonFormSet, can_delete=True, extra=0)
The piece above caused the form to never save, I dunno why. Removing this and doing a relatively hacky workaround fixed it for me. Now I have a ModelSelect named company
in the form which is filled in using JavaScript.
I have a Django view that basically only displays and saves a formset, the code of that is:
def manage_company_contact_persons(request, company_id):
company = get_object_or_404(Company, id=company_id)
if request.method == 'POST':
print request.POST
cpfs = forms.ContactPersonFormSet(queryset=company.contact_persons.all(), data=request.POST)
if cpfs.is_valid():
for cpf in cpfs:
print cpf.errors
cpf.save()
else:
cpfs = forms.ContactPersonFormSet(queryset=company.contact_persons.all())
return render_to_response('company/manage/admin-crm-company-contactpersons-new.html',
{'contactpersons': cpfs,
'company': company,},
context_instance=RequestContext(request))
The purpose of this is to allow the user to create/update/delete contractpersons from the database. The ContactPersonFormSet is defined as follows:
class SingleContactPersonForm(forms.ModelForm):
# Fields for the User model
first_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'w170'}), required=True, label=_(u'First name'))
last_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'w170'}), required=True, label=_(u'Last name'))
email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'w170'}), required=True, label=_(u'E-Mail'))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'w170'}), required=False, label=_(u'Password'))
# Fields for the Address model
zip_code = forms.CharField(widget=forms.TextInput(attrs={'class': 'w100 address'}), required=False, label=_(u'Zip code + house number'))
house_number = forms.CharField(widget=forms.TextInput(attrs={'class': 'w60 address'}), required=False, label=_(u'Zip code + house number'))
street = forms.CharField(widget=forms.TextInput(attrs={'class': 'w170 address'}), required=False, label=_(u'Street'))
city = forms.CharField(widget=forms.TextInput(attrs={'class': 'w170 address'}), required=False, label=_(u'City'))
country = forms.ModelChoiceField(queryset=Country.objects.all(), widget=forms.Select(attrs={'class address': 'w170'}), required=False, label=_(u'Country'))
def __init__(self, *args, **kwargs):
super(SingleContactPersonForm, self).__init__(*args, **kwargs)
### If there is an instance, get it to fill extra fields
def save(self, commit=True, *args, **kwargs):
'''Saves the whole contact Person to the database, including the address and the user.'''
super(SingleContactPersonForm, self).save(*args, commit=commit, **kwargs)
### save data in other models
if commit:
super(SingleContactPersonForm, self).save()
return self
class Meta:
model = Person
fields = ['job_title', 'telephone_number', 'mobile_number', 'fax']
widgets = {'job_title': forms.TextInput(attrs={'class': 'w170'}),
'telephone_number': forms.TextInput(attrs={'class': 'w170'}),
'mobile_number': forms.TextInput(attrs={'class': 'w170'}),
'fax': forms.TextInput(attrs={'class': 'w170'}),
}
ContactPersonFormSet = forms.models.modelformset_factory(model=Person, form=SingleContactPersonForm, can_delete=True, extra=0)
The issue is that for some reason only the original contact person is saved to the database. New contact persons are never created, as the save() method for the new ones is never called. All the data is in the POST as far as I can see. The formset is also valid, because the original items do get their save() function called.
Is it maybe falling over the fact that I include an empty 'id' in the POST data?
The data in the POST is:
{u'csrfmiddlewaretoken': [u'056d5042e73322c8166011e27108d362'],
u'form-0-city': [u'Culemborg'],
u'form-0-country': [u'155'],
u'form-0-email': [u'[email protected]'],
u'form-0-fax': [u'0345750249'],
u'form-0-first_name': [First'],
u'form-0-house_number': [u'7'],
u'form-0-id': [u'69'],
u'form-0-job_title': [u'Job'],
u'form-0-last_name': [u'Name'],
u'form-0-mobile_number': [u''],
u'form-0-password': [u''],
u'form-0-street': [u'Street'],
u'form-0-telephone_number': [u'0123456789'],
u'form-0-zip_code': [u'4104AN'],
u'form-1-city': [u'Culemborg'],
u'form-1-country': [u'155'],
u'form-1-email': [u'[email protected]'],
u'form-1-fax': [u''],
u'form-1-first_name': [u'Second'],
u'form-1-house_number': [u'7'],
u'form-1-id': [u''],
u'form-1-job_title': [u'Function'],
u'form-1-last_name': [u'Name'],
u'form-1-mobile_number': [u''],
u'form-1-password': [u''],
u'form-1-street': [u'Nijverheidsweg'],
u'form-1-telephone_number': [u'0987654321'],
u'form-1-zip_code': [u'4104AN'],
u'form-INITIAL_FORMS': [u'1'],
u'form-MAX_NUM_FORMS': [u'1000'],
u'form-TOTAL_FORMS': [u'1'],
u'form-__prefix__-city': [u''],
u'form-__prefix__-country': [u''],
u'form-__prefix__-email': [u''],
u'form-__prefix__-fax': [u''],
u'form-__prefix__-first_name': [u''],
u'form-__prefix__-house_number': [u''],
u'form-__prefix__-id': [u''],
u'form-__prefix__-job_title': [u''],
u'form-__prefix__-last_name': [u''],
u'form-__prefix__-mobile_number': [u''],
u'form-__prefix__-password': [u''],
u'form-__prefix__-street': [u''],
u'form-__prefix__-telephone_number': [u''],
u'form-__prefix__-zip_code': [u'']}
Upvotes: 2
Views: 2084
Reputation: 8488
Edit:
I think i found your error. You forgot to pass "data" arg to that "super" call. You wrote this:
class BaseContactPersonFormSet(forms.models.BaseModelFormSet):
def __init__(self, company, data=None, **kwargs):
super(BaseContactPersonFormSet, self).__init__(**kwargs)
for form in self:
form.company = company
ContactPersonFormSet = forms.models.modelformset_factory(model=Person, form=SingleContactPersonForm, formset=BaseContactPersonFormSet, can_delete=True, extra=0)
but you should write this:
class BaseContactPersonFormSet(forms.models.BaseModelFormSet):
def __init__(self, company, data=None, **kwargs):
super(BaseContactPersonFormSet, self).__init__(data, **kwargs)
for form in self:
form.company = company
ContactPersonFormSet = forms.models.modelformset_factory(model=Person, form=SingleContactPersonForm, formset=BaseContactPersonFormSet, can_delete=True, extra=0)
OLD ANSWER:
Try changing these lines:
if cpfs.is_valid():
for cpf in cpfs:
print cpf.errors
cpf.save()
for these lines:
if cpfs.is_valid():
cpfs.save()
Taken from here
Upvotes: 1