使用新的“虚拟"保存基于类的视图表单集项目.柱子

2022-01-24 00:00:00 python django save formset

问题描述

我在表单中有一个表格,由表单集生成.

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_onebox_twoSum ,但没有成功.我也尝试过以这种方式生成表单,但这不起作用:
  • This save is not working at all. It worked when it was only one form, but not for the formset
  • I tried to generate the column amount 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
<form action="" method="post"></form><桌子>{% csrf_token %}{{ formset.management_form }}{% for formset %}<头><tr>{% if forloop.first %}<th>{{ form.code.label_tag }} </th><th>{{ form.description.label_tag }} </th><th><label>金额:</label></th><th>{{ form.box_one.label_tag }} </th><th>{{ form.box_two.label_tag }} </th>{% 万一 %}</tr></头><身体><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 %}<输入类型=提交"值=更新"/></表></表格></div>...

... <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 表达式 将两个数字字段的值相加

Annotating query with virtual column

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.

相关文章