Я работаю над некоторыми формами Django, для которых база кода наследуется от кого-то другого, что хорошо, но добавляет к путанице.Django: Несколько форм в форме
Я пытаюсь добавить второй набор форм в форму. Когда добавляется второй набор форм, оба набора форм появляются на странице, но, по-видимому, не содержат никаких форм на бэкэнд. Вот пример моего кода (я добавил больше, чем, вероятно, рекомендуется, но я не хочу пропустить что-то важное):
view.py:
class Thing(StaffRequiredMixin, DetailView):
model = models.Thing
def post(self, request, *args, **kwargs):
...
context = self.get_context_data(**kwargs)
dispatch = {
"thing_form": self.handle_thing_form,
...
}
return dispatch[self.request.POST.get("form_name")](context)
...
def get_context_data(self, *args, **kwargs):
context = super(Thing, self).get_context_data(*args, **kwargs)
thing = self.model.objects.get(pk=self.kwargs["pk"])
context["thing"] = thing
to_handle = self.request.POST.get("form_name")
if to_handle == "thing_form":
context["thing_form"] = forms.Thing(
self.request.POST,
instance=thing)
context["formset1"] = forms.FormSet1(
self.request.POST,
queryset=models.Model1.objects.filter(thing=self.object),
prefix="thing1")
context["formset2"] = forms.FormSet2(
self.request.POST,
queryset=models.Model2.objects.filter(thing=self.object),
prefix="thing2")
else:
context["thing_form"] = forms.Thing(
instance=thing,
user=self.request.user)
context["formset1"] = forms.FormSet1(
queryset=models.Model1.objects.filter(thing=self.object),
prefix="stuff1")
context["formset2"] = forms.FormSet2(
queryset=models.Model2.objects.filter(thing=self.object),
prefix="stuff2")
# Other to_handle stuff
...
return context
def handle_thing_form(self, context):
form = context['thing_form']
formset1 = context['formset1']
formset2 = context['formset2']
if form.is_valid() and formset1.is_valid() and formset2.is_valid():
# Do some form logic
...
form.save()
# Formset stuff:
# here, the formsets contain no forms
changed_1 = [f for f in formset1 if f.has_changed()]
changed_2 = [f for f in formset2 if f.has_changed()]
for a_form in changed_1:
#Do some formset logic
...
a_form.save()
for a_form in changed_2:
#similar to 1
return HttpResponseRedirect(self.get_next_url())
return self.render_to_response(context)
forms.py:
class Form1(ModelForm):
class Meta:
model = models.Model1
fields = ("field1", "field2", ...)
def __init__(self, *args, **kwargs):
super(Form1, self).__init__(*args, **kwargs)
# Some readonly widget stuff etc
...
class Form2(ModelForm):
#Same idea as Form1
...
FormSet1 = modelformset_factory(models.Model1, form=Form1, extra=0)
FormSet2 = modelformset_factory(models.Model2, form=Form2, extra=0)
шаблона:
<form id="thing-form" method="post">
<input type="hidden" name="form_name" value="thing_form" />
{% for field in thing_form.visible_fields %}
{{ field }}
...
{% endfor %}
<a id="add-form1">Add</a>
{{formset1.management_form}}
<div id="formset1-div">
{% for form in formset1.forms %}
{{form.id}}
{% for field in form.visible_fields %}
<div class="controls">
{{field}}
</div>
{% endfor %}
{% endfor %}
</div>
<div id="empty-form1>
{% for field in formset1.empty_form.visible_fields %}
<div class="controls">
{{field}}
</div>
{% endfor %}
</div>
{{formset2.management_form}}
<div id="formset2-div">
{# same idea as above #}
...
</div>
<button type="submit">Update</button>
</form>
JavaScript:
$(document).ready(function(){
$('#add-form1').click(function() {
$('#formset1-div').prepend($('#empty_form1').html().replace(/__prefix__/g, 'thing1'));
$('#id_form-TOTAL_FORMS').val(parseInt('thing1') + 1);
});
if ($("#formset1-div input").length === 0){
$("#add-form1").trigger("click");
}
// Similar button stuff for formset2
...
})
В любом случае, я добавил много здесь, но я сделал это, потому что я не уверен, где я ошибся, или даже если то, что я пытаюсь сделать, возможно.
Нет, вы не глупы, тем не менее, шаблоны Django не поддаются сложным веб-интерфейсам. Как и вы, я обнаружил, что шаблоны вскоре стали слишком хрупкими для поддержания. Несколько вложенных форм в конечном итоге привели меня в AngularJS, используя Django и Django REST Framework в качестве бэкэнд. Я нашел, что комбо работает неплохо. Просто мой 2 ¢, рад, что вы это поняли. – Fiver