Open MrkGrgsn opened 1 year ago
That doesn't work for my use-case: form_list is supplied on the class, but dynamically updated based on previous data. Specifically, it injects duplicates of form Y (with different data) n times based on the selection of form X.
@schinckel Thanks for having a look. I envisaged your use case being met with a custom get_form_list()
of this kind:
def get_form_list(self):
form_list = OrderedDict(
# Forms previously in self.form_list
[("step1", FormX)],
)
# Forms injected as required per submitted data.
form_data = self.get_cleaned_data_for_step("step1", form_cls=FormX) or {}
if form_data.get("foo", False):
for i in range(2):
form_list[f"step{i}"] = FormY
return form_list
I have to admit I'm not certain where it falls down (in preparing initial data and form args?) but maybe I can change tack if you can clarify where the sticking point is.
Please resolve git conflicts.
Hi @cclauss, thanks for looking at this merge request. I'm happy to resolve the conflicts if the change is actually going somewhere but I've had only one response and that was to the effect that it doesn't meet one of the known use cases so I'm not clear that it has a future.
Is this PR going anywhere? There seemed to be a fair bit of interest in allowing the use of get_cleaned_data_for_step() in condition callables. The fix for the recursion error did nothing in this regard, so pinning to 2.3 is still necessary.
@claudep As noted, there are existing use cases that were broken in https://github.com/jazzband/django-formtools/pull/209 and are still broken, despite https://github.com/jazzband/django-formtools/issues/220, requiring some projects, including my own, to pin to 2.3. This PR may not be the best solution but it explores some of the challenges of a fix; could you review please and provide some feedback so we can move toward a solution?
This is an attempt to fix #220 while restoring pre-#209 features and supporting dynamic form lists using custom
get_form_list()
implementations.The solution has two parts:
get_form_class()
usesself.form_list
as a key to determine whether the class is implemented using the original form list generation strategy (ie,form_list
andcondition_dict
) or the more dynamic approach (ie, overridingget_form_list()
). Ifform_list
is populated, the strategy is inferred to be the original one.get_cleaned_data_for_step()
now supports an optional form class argument so thatget_form()
doesn't need to callget_form_list()
and trigger infinite recursion. This enables customget_form_list()
implementations to access submitted data from other steps.Change 1 will be a breaking change for implementations that have a custom
get_form_list()
- the developers would need to stop passing any forms viaas_view()
or setting them in the class, and may need to modifyget_form_list()
to adapt for this. Another option would be an explicit argument toas_view()
that selects the form list generation strategy butform_list
seems an adequate and natural key for this purpose. Change 1 ensure that the original form list generation strategy is not prone to infinite recursion.re: change 2, there are probably some different and possibly better ways of handling this, but I think this way is okay and backwards compatible. In the fully dynamic / custom
get_form_list()
approach, the form class for a given step is known only toget_form_list()
so it must explicitly tell the other methods what form class to instantiate for each step.I explored another option where the infinite recursion was broken by having
get_form_list()
return a partial cached form list. This allowed callables incondition_dict
to access data from earlier steps. This would replace change 1 but something like change 2 would still be required for customget_form_list()
methods. I liked this option because it introduced caching but it was more complicated and it broke a test that implied that changingcondition_dict
during request handling was supported. Not sure what the use case for that would be.Anyway, hit me with your feedback. Additional manual testing is needed. I have run the test suite but not tried it in any projects, so please try it out. It also needs docs updates.