2👍
Sharp-eyed readers (which, it turns out, does not include me, hence this problem) will note that my output includes at the end of each form:
`<tr><th></th><td><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>`
Now, when that is substituted into <tr id="existing_docs_row"><td colspan="2">{{ existing_articles.management_form }}{% for f in existing_articles %}<div>{{ f }}</div>{% endfor %}</td></tr>
that leads to invalid markup (a tr
inside a tr
!).
So, it turns out that the template was generating the second form, but the browser’s error recovery methods (in chrome, disregarding a lot of the invalid markup; in firefox, floating the second form to elsewhere in the DOM) created the appearance that the second form wasn’t being generated.
To summarise: just examining the DOM mislead me. Try to force your browser to choke on errors, and look at the raw markup.