Python Django在UpdateView中删除内联表单集记录
我有一个UpdateView,其中包含一个表单和一个与表单模型相关的InlineFormetSet(我简化了下面的代码):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
#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
)