How to save Django ModelFormSet?

亡梦爱人 提交于 2021-02-07 20:31:37

问题


I'm quite desperate now and I cannot figure this out. To me it should be easy to do, but I have not come across any answers that explains this.

Two models with no foreign keys between them:

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)

One modelformset to save to ModelB.

SalaryFormSet = modelformset_factory(Salary, extra=0)

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

In formfile.html:

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

As soon as I hit Submit, the formset is parsed as invalid and f.errors states (for each row in 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>

I just want to have surname and name from all rows in Employee preloaded into SalaryFormSet, and I should enter salary for each row and save them to Salary. The records in Salary should not be updated, but a new entry should be created.

The Employee model already has records created from the admin site. As employees' salaries increase, I will generate payslips from Salary model and capture the relevent salary from the latest date.

If I change the queryset to queryset=Salary.objects.none() and change SalaryFormSet to extra=2, the template is rendered empty. If I insert surnames, names and salary manually, the formset saves correctly. Two new entries in Salary. Why can't I just have the name preloaded (should I load them as str()?) and manually add the salary?


回答1:


As I said in the comment, it doesn't make sense to pass a queryset of Employees to the instantiation of the Salary formset. I think given you're trying to keep these two models completely separate for whatever reason, and you want to create new Salary instances each time, you would be better off just passing a set of initial data.

This is slightly tricky, because initial only applies to extra forms, and extra is set by the formset factory, so you need to do it in the view. Something like this:

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



回答2:


This is just to summarize the answer, based on Daniel Roseman's solution.

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

In forms.py:

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

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


来源:https://stackoverflow.com/questions/28623544/how-to-save-django-modelformset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!