Django - 带有试图保存重复记录的内联表单集的 UpdateView?
Django - UpdateView with inline formsets trying to save duplicate records?
我有一个 Expense
模型和一个 ExpenseLineItem
模型。就像典型的 expense/invoice 一样,一笔费用可以有多个行项目来构成一张发票的总成本。我正在尝试使用基于 class 的视图来创建和更新费用。我已经成功地编写了 CreateView
代码,以使用多个费用明细项目来产生新的费用。
我的问题是当我尝试更新已有多个费用明细项目的现有费用时。下面是我的代码,我不知道问题出在哪里。 mixin(TitleMixin
、CancelSuccessMixin
、SelectedApartment
)是我的并且工作正常。
我收到一个错误,我认为这意味着它正在尝试保存 ExpenseLineItems
的 new 副本,但失败了,因为它们已经存在。几乎就像我没有提供 instance
论点一样。
我做错了什么?
forms.py
class ExpenseForm(ModelForm):
class Meta:
model = Expense
fields = ['apart', 'inv_num', 'vendor', 'due_date']
ExpenseLineItemFormset = inlineformset_factory(Expense, ExpenseLineItem, fields=('description', 'account', 'amt'), can_delete=False)
这是我的 ExpenseUpdate
观点:
class ExpenseUpdate(TitleMixin, CancelSuccessMixin, SelectedApartment, UpdateView):
model = Expense
form_class = ExpenseForm
template_name = 'accounting/expense.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(instance = self.object)
return self.render_to_response(self.get_context_data(form = form, expense_line_item_form = expense_line_item_form))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(self.request.POST, instance=self.object)
if (form.is_valid() and expense_line_item_form.is_valid()):
return self.form_valid(form, expense_line_item_form)
return self.form_invalid(form, expense_line_item_form)
def form_valid(self, form, expense_line_item_form):
self.object = form.save()
expense_line_item_form.instance = self.object
expense_line_item_form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, expense_line_item_form):
return self.render_to_response(self.get_context_data(form=form, expense_line_item_form=expense_line_item_form))
我得到的错误代码:
MultiValueDictKeyError at /stuff/2/accounting/update-expense/25/
"u'expenselineitem_set-0-id'"
Request Method: POST
Request URL: http://localhost:8000/stuff/2/accounting/update-expense/25/
Django Version: 1.8.3
Exception Type: MultiValueDictKeyError
Exception Value:
"u'expenselineitem_set-0-id'"
Exception Location: /usr/local/lib/python2.7/dist-packages/django/utils/datastructures.py in __getitem__, line 322
编辑:我模板的相关部分:
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% load widget_tweaks %}
<div class="row">
<div class="col-md-12">
<table class="table table-tight">
<thead>
<th>Description</th>
<th class="text-right">Account</th>
<th class="text-right">Amount</th>
</thead>
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.description|attr:'cols:29' }}</td>
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-md-12 text-right">
<a href="{{ cancel }}" class="btn btn-default btn-lg">Cancel</a>
<input class="btn btn-success btn-lg" type="submit" value="Post" />
</div>
<br><br>
</form>
编辑——工作表单模板我想我会添加我的模板的工作版本,如果其他人需要的话:
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.id }} {{ eli.description|attr:'cols:29' }}</td> <!-- <<==== Here's where I simply added {{ eli.id }}. That's all I changed :) -->
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
您需要在表单集中包含每个表单的表单 ID(它不会向用户显示,因为它呈现为隐藏输入)。如果没有该表格,POST 数据中将缺少该值,您会得到一个 KeyError
,如您所见。
来自formset docs:
Notice how we need to explicitly render {{ form.id }}
. This ensures that the model formset, in the POST case, will work correctly. (This example assumes a primary key named id. If you’ve explicitly defined your own primary key that isn’t called id, make sure it gets rendered.)
在您的例子中,您正在使用 {% for eli in expense_line_item_form %}
遍历表单集,因此您需要包含 {{ eli.id }}
.
我有一个 Expense
模型和一个 ExpenseLineItem
模型。就像典型的 expense/invoice 一样,一笔费用可以有多个行项目来构成一张发票的总成本。我正在尝试使用基于 class 的视图来创建和更新费用。我已经成功地编写了 CreateView
代码,以使用多个费用明细项目来产生新的费用。
我的问题是当我尝试更新已有多个费用明细项目的现有费用时。下面是我的代码,我不知道问题出在哪里。 mixin(TitleMixin
、CancelSuccessMixin
、SelectedApartment
)是我的并且工作正常。
我收到一个错误,我认为这意味着它正在尝试保存 ExpenseLineItems
的 new 副本,但失败了,因为它们已经存在。几乎就像我没有提供 instance
论点一样。
我做错了什么?
forms.py
class ExpenseForm(ModelForm):
class Meta:
model = Expense
fields = ['apart', 'inv_num', 'vendor', 'due_date']
ExpenseLineItemFormset = inlineformset_factory(Expense, ExpenseLineItem, fields=('description', 'account', 'amt'), can_delete=False)
这是我的 ExpenseUpdate
观点:
class ExpenseUpdate(TitleMixin, CancelSuccessMixin, SelectedApartment, UpdateView):
model = Expense
form_class = ExpenseForm
template_name = 'accounting/expense.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(instance = self.object)
return self.render_to_response(self.get_context_data(form = form, expense_line_item_form = expense_line_item_form))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(self.request.POST, instance=self.object)
if (form.is_valid() and expense_line_item_form.is_valid()):
return self.form_valid(form, expense_line_item_form)
return self.form_invalid(form, expense_line_item_form)
def form_valid(self, form, expense_line_item_form):
self.object = form.save()
expense_line_item_form.instance = self.object
expense_line_item_form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, expense_line_item_form):
return self.render_to_response(self.get_context_data(form=form, expense_line_item_form=expense_line_item_form))
我得到的错误代码:
MultiValueDictKeyError at /stuff/2/accounting/update-expense/25/
"u'expenselineitem_set-0-id'"
Request Method: POST
Request URL: http://localhost:8000/stuff/2/accounting/update-expense/25/
Django Version: 1.8.3
Exception Type: MultiValueDictKeyError
Exception Value:
"u'expenselineitem_set-0-id'"
Exception Location: /usr/local/lib/python2.7/dist-packages/django/utils/datastructures.py in __getitem__, line 322
编辑:我模板的相关部分:
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% load widget_tweaks %}
<div class="row">
<div class="col-md-12">
<table class="table table-tight">
<thead>
<th>Description</th>
<th class="text-right">Account</th>
<th class="text-right">Amount</th>
</thead>
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.description|attr:'cols:29' }}</td>
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-md-12 text-right">
<a href="{{ cancel }}" class="btn btn-default btn-lg">Cancel</a>
<input class="btn btn-success btn-lg" type="submit" value="Post" />
</div>
<br><br>
</form>
编辑——工作表单模板我想我会添加我的模板的工作版本,如果其他人需要的话:
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.id }} {{ eli.description|attr:'cols:29' }}</td> <!-- <<==== Here's where I simply added {{ eli.id }}. That's all I changed :) -->
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
您需要在表单集中包含每个表单的表单 ID(它不会向用户显示,因为它呈现为隐藏输入)。如果没有该表格,POST 数据中将缺少该值,您会得到一个 KeyError
,如您所见。
来自formset docs:
Notice how we need to explicitly render
{{ form.id }}
. This ensures that the model formset, in the POST case, will work correctly. (This example assumes a primary key named id. If you’ve explicitly defined your own primary key that isn’t called id, make sure it gets rendered.)
在您的例子中,您正在使用 {% for eli in expense_line_item_form %}
遍历表单集,因此您需要包含 {{ eli.id }}
.