I have a problem with needing to provide multiple model backed forms on the same page. I understand how to do this with single forms, i.e. just create both the forms call them something different then use the appropriate names in the template.
Now how exactly do you expand that solution to work with modelformsets? The wrinkle, of course, is that each 'form' must be rendered together in the appropriate fieldset.
For example I want my template to produce something like this:
Home Base Description: Want ice cream? Home Base Description: Want ice cream?
I am using a loop like this to process the results (after form validation)
base_models = base_formset.save(commit=False)
like_models = like_formset.save(commit=False)
for base_model, likes_model in map(None, base_models, likes_models):
which works as I'd expect (I'm using map because the # of forms can be different). The problem is that I can't figure out a way to do the same thing with the templating engine. The system does work if I layout all the base models together then all the likes 开发者_StackOverflow中文版models after wards, but it doesn't meet the layout requirements.
EDIT: Updated the problem statement to be more clear about what exactly I'm processing (I'm processing models not forms in the for loop)
In the view:
forms = itertools.izip(base_forms, likes_forms)
In the template:
{% for (base_form,like_form) in forms %}
After doing a fair amount of poking around and hack experimenting I've come up with the following solution thanks in huge part to Ignacio Vazquez-Abrams :)
In the view:
forms = itertools.izip_longest((None,),base_formset.forms, likes_formset.forms)
In the template:
{% for (garbage1, base_form, like_form, garbage2) in forms %}
The astute reader might notice that the number of arguments in the unpacking list is one larger than what was given to the izip_longest() method. You might also note that there is an effectively blank list as the first argument.
I could never get the template to display the first argument in the list hence the dummy first argument. Also I found that N-1 list elements were being rendered in the template. I also stumbled upon the fact that the template doesn't much care about a size mismatch so by padding the front and the back I was able to get the forms I actually wanted to display!
NOTE: When processing the POST I simply construct the formsets that I'm working with since all the phantom data isn't being sent back through the POST.
Certainly not the cleanest solution and it is probably extremely vulnerable to upgrade breakage, but it's practical enough to work for me for now.
精彩评论