如何保存Django ModelFormSet?

时间:2015-02-20 07:19:05

标签: python django modelform formset

我现在非常绝望,我无法弄清楚这一点。对我而言应该很容易做到,但我没有遇到任何解释这个问题的答案。

两个模型之间没有外键:

class Employee(models.Model):
    surname = models.CharField(max_length=100)
    name = models.CharField(max_length=100)


class Salary(models.Model):
    date = models.DateField(auto_now_add=True)
    surname = models.CharField(max_length=100)
    name = models.CharField(max_length=100)
    salary = models.DecimalField(max_digits=20, decimal_places=2)

一个要保存到ModelB的modelformset。

SalaryFormSet = modelformset_factory(Salary, extra=0)

然后在views.py中:

def createForm(request):
    formset = SalaryFormSet(queryset=Employee.objects.all())
    return render(request, 'formfile.html', {'formset': formset})

def submitForm(request)
    f = ModelBFormSet(request.POST)
    if f.is_valid():
        f.save()
        return HttpResponse('Submitted successfully')
    else:
        return HttpResponse(f.errors, request.POST)

在formfile.html中:

<form action="submitForm/" method="post">
    {{ formset.management_form }}
    <table>
        {{ formset }}
    </table>
    {% csrf_token %}
    <input type="submit" value="Submit">
</form> 

一旦我点击提交,表单集就会被解析为无效而f.errors状态(对于Employee中的每一行):

<ul class="errorlist"><li>id<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>

我只想将Employee中所有行的姓氏和名称预先加载到SalaryFormSet中,我应该输入每行的工资并将它们保存到Salary。不应更新Salary中的记录,但应创建新条目。

Employee模型已经有从管理站点创建的记录。随着员工工资的增加,我将从薪资模型中生成工资单,并从最近的日期获得相关工资。

如果我将queryset更改为queryset = Salary.objects.none()并将SalaryFormSet更改为extra = 2,则模板将呈现为空。如果我手动插入姓氏,名称和工资,则表单集可以正确保存。薪资中的两个新条目。为什么我不能预先加载名称(我应该将它们加载为str()?)并手动添加薪水?

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,将Employees的查询集传递给Salary formset的实例化是没有意义的。我认为,鉴于您无论出于何种原因而试图将这两个模型完全分开,并且您希望每次都创建新的Salary实例,您最好只传递一组initial数据。

这有点棘手,因为initial仅适用于额外的表单,而extra由formset工厂设置,因此您需要在视图中执行此操作。像这样:

employees = Employee.objects.values('name', 'surname')
SalaryFormSet = modelformset_factory(Salary, extra=len(employees))
formset = SalaryFormSet(initial=employees, queryset=Salary.objects.none())

答案 1 :(得分:1)

这只是为了总结答案,基于Daniel Roseman的解决方案。

在models.py中:

class Employee(models.Model):
    surname = models.CharField(max_length=100)
    name = models.CharField(max_length=100)


class Salary(models.Model):
    date = models.DateField(auto_now_add=True)
    surname = models.CharField(max_length=100)
    name = models.CharField(max_length=100)
    salary = models.DecimalField(max_digits=20, decimal_places=2)

在forms.py中:

employees = Employee.objects.values('surname', 'name')
SalaryFormSet = modelformset_factory(Salary, extra=len(employees)

在views.py中:

def createForm(request):
    formset = SalaryFormSet(initial=employees, queryset=Salary.objects.none())
    return render(request, 'formfile.html', {'formset': formset})

def submitForm(request)
    f = ModelBFormSet(request.POST)
    if f.is_valid():
        f.save()
        return HttpResponse('Submitted successfully')
    else:
        return HttpResponse(f.errors, request.POST)