Python Django在UpdateView中删除内联表单集记录

Python Django在UpdateView中删除内联表单集记录,python,django,Python,Django,我有一个UpdateView,其中包含一个表单和一个与表单模型相关的InlineFormetSet(我简化了下面的代码): #models.py 课堂笔记(模型): content=models.TextField() 类对话框(模型): message=models.TextField() 注=模式。外键(注) #views.py 类NoteUpdateView(UpdateView): 型号=注 form_class=NoteForm def获取上下文数据(自身,**kwargs): con

我有一个UpdateView,其中包含一个表单和一个与表单模型相关的InlineFormetSet(我简化了下面的代码):

#models.py
课堂笔记(模型):
content=models.TextField()
类对话框(模型):
message=models.TextField()
注=模式。外键(注)
#views.py
类NoteUpdateView(UpdateView):
型号=注
form_class=NoteForm
def获取上下文数据(自身,**kwargs):
context=super(NoteUpdateView,self)。获取上下文数据(**kwargs)
self.object=self.get_object()
dialogFormset=inlineformset\u工厂(注意,
对话
字段=“”“所有”,
额外费用=0)
dialog=dialogFormset(实例=self.object)
上下文['dialog']=dialog
返回上下文
def post(自我、请求、*args、**kwargs):
form=self.get\u form(self.get\u form\u class())
dialog\u form=DialogFormset(self.request.POST,instance=Note.objects.get(id=self.kwargs['pk']))
如果(form.is\u valid()和dialog\u form.is\u valid()):
返回self.form\u valid(表单、结果表单、对话框表单)
其他:
返回self.form\u无效(表单、结果表单、对话框表单)
定义表单有效(自身、表单、结果表单、对话框表单):
self.object,created=Note.objects.update_或_create(pk=self.kwargs['pk'],默认值=form.cleaned_数据)
对话框\表单保存()
返回HttpResponseRedirect(self.get_success_url())
def表单无效(自身、表单、结果表单、对话框表单):
返回self.render\u to\u response(self.get\u context\u data)(form=form,
结果形式=结果形式,
对话形式=对话形式)
NoteUpdateView
的目的是在向
Note/11
发出
GET
请求时,呈现现有的
Note
Dialog
。用户可以删除现有的
对话框
,该对话框不由上述代码处理

要处理删除,我可以在POST上执行以下操作:

1) 获取与请求的便笺相关的所有对话框记录: dialogs=Note.objects.filter(pk=self.kwargs['pk'])

2) 循环浏览self.request.POST,查看提交数据中包含的表单集是否也存在于上面创建的
对话框中

3) 如果记录是
对话框
,但未通过POST提交,则认为该对话框已被用户删除。因此,执行预成型删除操作


我相信我可以实施这些步骤。但因为我对Django的表格不太熟悉。我想知道是否有任何内置的类或方法可以用来自动化这些步骤。Django做我刚才描述的事情的方法是什么?

Django的方法是检查是否有人为您创建了一个库:-)

因此,看看卓越的django额外视图,它是。我经常使用它,而且效果非常好。在您的情况下,您的视图会变成这样:

from extra_views import InlineFormSetView

class NoteUpdateView(InlineFormSetView):
    model = Note
    inline_model = Dialog
    form_class = NoteForm
    extra = 0

    def get_context_data(self, **kwargs):
        context = super(NoteUpdateView ,self).get_context_data(**kwargs)
        context['dialog'] = context['formset']
        return context

如果将模板更新为将表单集引用为“formset”,则可以跳过
。获取上下文\u数据
方法。

好的,我找到了问题所在。我遇到的问题是由于使用了django脆饼。让我解释一下发生了什么:

当Django呈现
InlineFormSet
时,它被设置为
True
。当此属性设置为True时,将在呈现的HTML中插入一个隐藏的输入字段:

<input type="hidden" name="dialog_set-0-DELETE" id="id_dialog_set-0-DELETE">
我需要
django crispy forms
将textarea标记的行号设置为3。因此,我必须明确地重新定义
Layout
下文本区域字段的外观。在使用
布局时,我没有意识到的是,没有在布局中定义的任何内容都不会在HTML中呈现

从代码的外观来看,我没有遗漏
对话框
模型中定义的任何字段。但是,我没有意识到的是,InlineFormSet附带的隐藏字段不会在HTML中呈现,除非我在布局对象和模板中明确定义它们。要使formset和inlineformset正常工作,需要以下隐藏输入:

  • 。它们在HTML中的外观如下所示:

    <input id="id_dialog_set-TOTAL_FORMS" name="dialog_set-TOTAL_FORMS" type="hidden" value="1">
    <input id="id_dialog_set-INITIAL_FORMS" name="dialog_set-INITIAL_FORMS" type="hidden" value="1">
    <input id="id_dialog_set-MIN_NUM_FORMS" name="dialog_set-MIN_NUM_FORMS" type="hidden" value="0">
    <input id="id_dialog_set-MAX_NUM_FORMS" name="dialog_set-MAX_NUM_FORMS" type="hidden" value="1000">
    
    <input type="hidden" name="dialog_set-0-DELETE" id="id_dialog_set-0-DELETE"> 
    

    最后,现在一切都正常了

    谢谢托马斯,我一定会检查的!如果错误在模板代码中,它就不会解决您的问题。尽管如此,它还是让景色变得更好。
    <input type="hidden" name="dialog_set-0-DELETE" id="id_dialog_set-0-DELETE"> 
    
    <form method="post" action="{{ action }}" enctype="multipart/form-data" id="note_form">
        {% crispy form %}
    
        {# the management_form is covered here #}
        {{ dialog.management_form }}
    
        {% for form in dialog %}
            <div class="formset-container">
                <div class="dialog-title">
                    {% crispy form dialogHelper %}
                </div>
    
                {# the hidden fields are covered here #}
                {% for hidden in form.hidden_fields %}
                    {{ hidden }}
                {% endfor %}
    
             </div>
        {% endfor %}
    </form>
    
    #forms.py
    class DialogFormSetHelper(FormHelper):
     def __init__(self, *args, **kwargs):
        super(DialogFormSetHelper, self).__init__(*args, **kwargs)
        self.form_tag = False    
        self.disable_csrf = True 
        self.layout = Layout(
            Field('info1', rows='3'), 
            Field('info2', rows='3'),
            Field('DELETE')  # <- ADD THIS LINE
        )