jazzband / django-formtools

A set of high-level abstractions for Django forms
https://django-formtools.readthedocs.io
BSD 3-Clause "New" or "Revised" License
784 stars 135 forks source link

Attempting to implement conditional views generates the error RecursionError: maximum recursion depth exceeded #264

Open ghost opened 6 months ago

ghost commented 6 months ago

Hello! I'm trying to implement Django Wizard's conditional view in my project but I can't. Whenever I access my form page, I receive the error: RecursionError: maximum recursion depth exceeded .

I investigated what is generating this error with ipdb and found that the WizardView.get_cleaned_data_for_step(step) method

is causing the problem.

I would like help to know if I implemented the feature correctly or if this is a bug.

NT. I want it to work as follows:

In the PessoaForm form there is a checkbox field where my user must select one of two options: PF or PJ. If he selects PF then the next form displayed should be the PessoaFisicaForm and if he selects the PJ option, then the PessoaJuridicaForm form should be displayed.

These are my forms

Screenshot from 2024-01-18 15-40-35

This is my view Screenshot from 2024-01-18 15-41-33

and this is the callable that you create according to the documentation guidance

Screenshot from 2024-01-18 15-41-56

Error generated

Screenshot from 2024-01-18 16-11-22

pfouque commented 5 months ago

Hi, I faced a similar issue and ended up declaring the form_list with explicit naming:

class MyWizard(SessionWizardView):
    form_list: list[tuple[str, type[Form]]] = [
        ("pessoa", PessoaForm),
        ("fisica", PessoaFisicaForm),
        ("juridica", PessoaJuridicaForm),
    ]

    @staticmethod
    def show_fisica(wizard: SessionWizardView) -> bool:
        if pessoa_data := wizard.get_cleaned_data_for_step("pessoa"):
            return pessoa_data.get("tipo") == "fisica"
        return False

    @staticmethod
    def show_juridica(wizard: SessionWizardView) -> bool:
        if pessoa_data := wizard.get_cleaned_data_for_step("pessoa"):
            return pessoa_data.get("tipo") == "juridica":
                return company is None
        return True

    condition_dict = {
        "fisica": show_fisica,
        "juridica": show_juridica,
    }

Maybe it will work for you too... or you could try switching only the Form instead (by overriding get_form)