保存Django ModelFormset不会保存新对象

时间:2013-07-11 13:16:00

标签: django save django-forms formset

更新:发现错误......

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)

上面的部分导致表格永不保存,我不知道为什么。删除它并做一个相对hacky的解决方法为我修复它。现在我在表单中有一个名为company的ModelSelect,它使用JavaScript填充。


原始问题:

我有一个Django视图,基本上只显示和保存一个formset,代码是:

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))

这样做的目的是允许用户从数据库中创建/更新/删除Contractpersons。 ContactPersonFormSet定义如下:

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)

问题在于,由于某种原因,只有原始联系人才会保存到数据库中。永远不会创建新的联系人,因为永远不会调用新的联系人。据我所见,所有数据都在POST中。 formset也是有效的,因为原始项确实调用了save()函数。

是否可能会因为我在POST数据中包含一个空的“id”而失败?

POST中的数据是:

{u'csrfmiddlewaretoken': [u'056d5042e73322c8166011e27108d362'],
 u'form-0-city': [u'Culemborg'],
 u'form-0-country': [u'155'],
 u'form-0-email': [u'info@domain1.com'],
 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'info@domain2.com'],
 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'']}

1 个答案:

答案 0 :(得分:1)

修改

我想我发现了你的错误。你忘了将“数据”arg传递给那个“超级”电话。你写了这个:

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)

但你应该这样写:

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:

尝试更改这些行:

if cpfs.is_valid():
    for cpf in cpfs:
        print cpf.errors
        cpf.save()

这些行:

if cpfs.is_valid():
    cpfs.save()

取自here