我在表单中有一个表格,由表单集生成.
I have a table inside a form, generated by a formset.
在这种情况下,我的问题是在其中一项被修改后保存所有项目,添加一个新的虚拟"列作为其他两项的总和(仅在显示表格时生成,不保存).我尝试了不同的方法,但没有一种方法有效.
In this case, my problem is to save all the items after one of them is modified, adding a new "virtual" column as the sum of other two (that is only generated when displaying the table, not saved). I tried different ways, but no one is working.
问题:
save
根本不起作用.它只有一种形式时有效,但不适用于形式集amount
列生成为 box_one
和 box_two
的 Sum
,但没有成功.我也尝试过以这种方式生成表单,但这不起作用:save
is not working at all. It worked when it was only one form, but not for the formsetamount
as a Sum
of box_one
and box_two
without success. I tried generating the form this way too, but this is not working:
这个问题和上一个有关,但是这个新的更简单:使用 Django 从数据库预填充 HTML 表单表
StackOverflow 之前的相关问题已经很老了,对我不起作用.
This issue is related to this previous one, but this new one is simpler: Pre-populate HTML form table from database using Django
我正在使用 Django 2.0.2
Previous related issues at StackOverflow are very old and not working for me.
任何帮助将不胜感激.提前致谢.
I'm using Django 2.0.2
当前代码:
models.py
models.py
views.py
views.py
urls.py
urls.py
item_list.html
item_list.html
...
<div>
<form action="" method="post"></form>
<table>
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<thead>
<tr>
{% if forloop.first %}
<th>{{ form.code.label_tag }} </th>
<th>{{ form.description.label_tag }} </th>
<th> <label>Amount:</label> </th>
<th>{{ form.box_one.label_tag }} </th>
<th>{{ form.box_two.label_tag }} </th>
{% endif %}
</tr>
</thead>
<tbody>
<tr>
<td>{{ form.code }}</td>
<td>{{ form.description }}</td>
<td>{{ form.amount }}</td>
<td>{{ form.box_one }}</td>
<td>{{ form.box_two }}</td>
</tr>
</tbody>
{% endfor %}
<input type="submit" value="Update" />
</table>
</form>
</div>
...
Sum
是 聚合表达式 而不是在这种情况下您希望注释此查询的方式.相反,您应该使用 F 表达式 将两个数字字段的值相加
Sum
is an aggregate expression and is not how you want to be annotating this query in this case. Instead, you should use an F exrepssion to add the value of two numeric fields
qs.annotate(virtual_col=F('field_one') + F('field_two'))
所以你更正的查询集将是
So your corrected queryset would be
Item.objects.order_by('code__name').annotate(amount=F('box_one') + F('box_two'))
如果打算将该属性仅用于行级"操作,则 cezar 提供的答案非常有用.但是,如果您打算根据amount
进行查询,则需要对查询进行注释.
The answer provided by cezar works great if intend to use the property only for 'row-level' operations. However, if you intend to make a query based on amount
, you need to annotate the query.
您没有在视图类中提供 post
方法.您需要自己提供一个,因为您没有从为您提供一个的通用视图继承.请参阅 使用基于类的视图处理表单.您还应该考虑从处理表单的通用视图继承.例如 ListView
没有实现 post
方法,但 FormView
实现了.
You have not provided a post
method in your view class. You'll need to provide one yourself since you're not inheriting from a generic view that provides one for you. See the docs on Handling forms with class-based views. You should also consider inheriting from a generic view that handles forms. For example ListView
does not implement a post
method, but FormView
does.
请注意,您的模板也不会呈现表单错误.由于您正在手动呈现表单集,因此您应该考虑添加字段错误(例如 {{ form.field.errors}}
),以便在 HTML 中显示验证问题.请参阅关于手动渲染字段的文档.
Note that your template is also not rendering form errors. Since you're rendering the formset manually, you should consider adding the field errors (e.g. {{ form.field.errors}}
) so problems with validation will be presented in the HTML. See the docs on rendering fields manually.
此外,您可以在 post
方法中记录/打印错误.例如:
Additionally, you can log/print the errors in your post
method. For example:
def post(self, request, *args, **kwargs):
formset = MyFormSet(request.POST)
if formset.is_valid():
formset.save()
return SomeResponse
else:
print(formset.errors)
return super().post(request, *args, **kwargs)
如果表单未通过验证,您应该会在控制台/日志中看到错误.
Then if the form does not validate you should see the errors in your console/logs.
这篇关于使用新的“虚拟"保存基于类的视图表单集项目.柱子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!