Python 使用新的“保存基于类的视图表单集项”;虚拟的;柱

Python 使用新的“保存基于类的视图表单集项”;虚拟的;柱,python,django,save,formset,Python,Django,Save,Formset,我在表单中有一个由表单集生成的表 在这种情况下,我的问题是在修改其中一个项目后保存所有项目,添加一个新的“虚拟”列作为其他两个项目的总和(仅在显示表时生成,而不是保存)。 我尝试了不同的方法,但没有人在工作 问题: 此保存根本不起作用。当它只是一个表单时,它就起作用了,但对于表单集却不起作用 我试图将amount列生成为box\u one和box\u two的Sum,但没有成功。我也尝试过以这种方式生成表单,但不起作用: 此问题与前一个问题相关,但新问题更简单: StackOverflow

我在表单中有一个由表单集生成的表

在这种情况下,我的问题是在修改其中一个项目后保存所有项目,添加一个新的“虚拟”列作为其他两个项目的总和(仅在显示表时生成,而不是保存)。 我尝试了不同的方法,但没有人在工作

问题

  • 保存
    根本不起作用。当它只是一个表单时,它就起作用了,但对于表单集却不起作用
  • 我试图将
    amount
    列生成为
    box\u one
    box\u two
    Sum
    ,但没有成功。我也尝试过以这种方式生成表单,但不起作用:
此问题与前一个问题相关,但新问题更简单:

StackOverflow以前的相关问题非常陈旧,对我来说不起作用

我正在使用Django 2.0.2

任何帮助都将不胜感激。提前谢谢

当前代码:

models.py

views.py

url.py

item_list.html

。。。
{%csrf_令牌%}
{{formset.management_form}
{formset%中表单的%s}
{%if-forloop.first%}
{{form.code.label_tag}}
{{form.description.label_tag}
数量:
{{form.box\u one.label\u tag}
{{form.box\u two.label\u tag}
{%endif%}
{{form.code}
{{form.description}}
{{form.amount}}
{{form.box_one}
{{form.box_two}
{%endfor%}
...

您已经走上了正确的道路。所以你说你需要一个虚拟专栏。您可以在模型类中定义一个虚拟属性,它不会存储在数据库表中,但是它可以作为模型类的任何其他属性进行访问

这是您应该添加到模型类
项中的代码:

class Item(models.Model):
    # existing code

    @property
    def amount(self):
        return self.box_one + self.box_one
现在,您可以执行以下操作:

item = Item.objects.get(pk=1)
print(item.box_one) # return for example 1
print(item.box_two) # return for example 2
print(item.amount) # it will return 3 (1 + 2 = 3)
编辑:
通过
ModelForm
我们可以访问模型实例,从而访问其所有属性。在模板中呈现模型表单时,我们可以访问如下属性:

{{ form.instance.amount }}
虚拟财产
amount
背后的想法是将业务逻辑放在模型中,并遵循胖模型-瘦控制器的方法。因此,
amount
作为
box\u one
box\u two
的总和,可以在不同的位置重复使用,而无需代码重复。

使用虚拟列注释查询
Sum
是一个函数,在本例中,它不是您希望注释此查询的方式。相反,您应该使用来添加两个数值字段的值

qs.annotate(virtual_col=F('field_one') + F('field_two'))
因此,您的更正查询集将是

Item.objects.order_by('code__name').annotate(amount=F('box_one') + F('box_two'))
如果只打算将财产用于“行级”操作,cezar提供的答案非常有效。但是,如果要基于
金额进行查询,则需要对查询进行注释

保存表单集 您尚未在视图类中提供
post
方法。您需要自己提供一个,因为您不是从为您提供一个的通用视图继承的。请参阅上的文档。还应该考虑从处理窗体的泛型视图继承。例如,
ListView
没有实现
post
方法,但是
FormView
实现了

请注意,模板也不会呈现表单错误。由于您正在手动绘制窗体集,因此应考虑添加字段错误(例如:代码> {{Fr.Fr.Engult} } /Cuth>),因此验证中的问题将在HTML中呈现。请参阅上的文档

此外,您可以在
post
方法中记录/打印错误。例如:

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)

然后,如果表单未验证,您应该在控制台/日志中看到错误。

Mmmm。。。如何使用item_list.html表单集中的属性?@AbelPaz请检查编辑。
ModelForm
保存模型实例(对象),因此可以访问其所有属性。我希望你能走上正确的道路。好的,我试试看。另外一个问题呢?单击
Update
按钮时如何保存所有表单数据?我的
save
方法根本不起作用。这是解决OP问题的好办法。但是应该注意,不能使用属性查询对象。例如,
Item.objects.filter(amount=x)
是不可能的。应将其视为仅可用于“行级”操作。@sytech谢谢!这是一个很好的观点。这里有一个解决办法。假设您希望检索金额小于10的所有对象:
pk_list=[item.objects.all()中的item.pk(如果item.amount<10];qs=Item.objects.filter(pk\u in=pk\u list)
。在
ItemForm的
save
方法中,您实际上想要实现什么?为什么要添加字段
说明
?它属于
code
。您应该只将一个或多个项目附加到代码中。从“项目详细信息页面”中的简单表单移动到表单集之前是这样的。它允许我在其页面中保存单个项目。现在我想将其更改为能够保存表单集中的所有字段
ItemForm
save
方法对我来说毫无意义。首先,使用
item=super().save(commit=False)
调用父方法,但不返回
item
。将值分配给
item.box\u一
item = Item.objects.get(pk=1)
print(item.box_one) # return for example 1
print(item.box_two) # return for example 2
print(item.amount) # it will return 3 (1 + 2 = 3)
{{ form.instance.amount }}
qs.annotate(virtual_col=F('field_one') + F('field_two'))
Item.objects.order_by('code__name').annotate(amount=F('box_one') + F('box_two'))
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)