总结一下问题:目前,您的代码成功引入了新的表单集,但是每个新的表单集都带有一个name
的属性form-0-title
(同上对于id
和其他属性)。此外,添加新的表单集后hx-get
最初创建的隐藏字段ManagementForm
将不再反映页面上的表单集数量。
需要什么
将新的表单集添加到站点后,我认为需要执行以下操作,以便 Django 可以处理表单提交。
-
更新value
输入元素中的属性id="id_form-TOTAL_FORMS"
因此该数字与之后页面上的实际表单集数量相匹配hx-get
引入新的表单集。
-
更新name
and id
新的表单集来自form-0-title
使用反映当前表单集总数的任何数字。
-
更新标签'for
属性以同样的方式。
您可以在客户端使用 Javascript 来完成此操作。或者,您可以在服务器端使用 Django 有效地执行相同的操作,然后 htmx 可以是完成其余操作所需的唯一 javascript。为此,我使用了empty_form
创建可根据需要更改的表单集的 html 内容。该工作显示在build_new_formset()
帮手,下。
Example
这是我正在做的工作:
forms.py
from django import forms
from django.forms import formset_factory
class BookForm(forms.Form):
title = forms.CharField()
author = forms.CharField()
BookFormSet = formset_factory(BookForm)
views.py
from django.utils.safestring import mark_safe
from app2.forms import BookFormSet
def formset_view(request):
template = 'formset.html'
if request.POST:
formset = BookFormSet(request.POST)
if formset.is_valid():
print(f">>>> form is valid. Request.post is {request.POST}")
return HttpResponseRedirect(reverse('app2:formset_view'))
else:
formset = BookFormSet()
return render(request, template, {'formset': formset})
def add_formset(request, current_total_formsets):
new_formset = build_new_formset(BookFormSet(), current_total_formsets)
context = {
'new_formset': new_formset,
'new_total_formsets': current_total_formsets + 1,
}
return render(request, 'formset_partial.html', context)
# Helper to build the needed formset
def build_new_formset(formset, new_total_formsets):
html = ""
for form in formset.empty_form:
html += form.label_tag().replace('__prefix__', str(new_total_formsets))
html += str(form).replace('__prefix__', str(new_total_formsets))
return mark_safe(html)
请注意:build_new_formset()
helper: formset.empty_form
将省略应该出现的索引号id
, name
and label
属性,并将使用"__prefix__"
。你想替换那个"__prefix__"
部分与适当的数字。例如,如果它是页面上的第二个表单集id
应该id_form-1-title
(更改自id_form-__prefix__-title
).
表单集.html
<form action="{% url 'app2:formset_view' %}" method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<p>{{ form }}</p>
{% endfor %}
<button type="button"
hx-trigger="click"
hx-get="{% url 'app2:add_formset' formset.total_form_count %}"
hx-swap="outerHTML">
Add formset
</button>
<input type="submit" value="Submit">
</form>
表单集_partial.html
<input hx-swap-oob="true"
type="hidden"
name="form-TOTAL_FORMS"
value="{{ new_total_formsets }}"
id="id_form-TOTAL_FORMS">
<p>{{ new_formset }}</p>
<button type="button"
hx-trigger="click"
hx-get="{% url 'app2:add_formset' new_total_formsets %}"
hx-swap="outerHTML">
Add formset
</button>
注意:隐藏的input
:对于每个新添加的表单集,value
of the input
元素有id="id_form-TOTAL_FORMS"
将不再反映页面上表单集的实际数量。您可以发送新的隐藏input
与您的表单集并包括hx-swap-oob="true"
在上面。然后 Htmx 将用新的替换旧的。
文档参考:https://docs.djangoproject.com/en/4.1/topics/forms/formsets/