NBajanca
NBajanca

Reputation: 3730

fields added in Django View not displayed with django-crispy-forms

I have this view (modified to make it simple to understand):

class MyCreateViewView(CreateView):

    model = SomeModel

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        form.helper = FormHelper(form)

        form.fields['additional_field'] = forms.BooleanField(label="Something", required=False)

        form.helper.add_input(Submit('submit', "Submit"))

        return form

Before adding the FormHelper, the field additional_field appeared on the template. Now it doesn't. The form in my template is basically one line: {% crispy form %}.

The django-crispy-forms docs don't show this approach because they are focused on using forms. I'm using the CreateView from Django that builds the form for me, so I don't need a form class.

So far, I noticed that doing form.helper = FormHelper(form) after programmatically adding the new field solves the problem. But this is not a solution because the view I presented here is a simplified version, and I actually have two views that are doing something similar. So I'm inheriting this class and adding extra fields in the views themselves (meaning FormHelper is already there).

Upvotes: 0

Views: 420

Answers (1)

NBajanca
NBajanca

Reputation: 3730

Solution: form.helper = FormHelper() (notice I'm passing the form as an argument)

Using an IDE led me to this error because the class is FormHelper(form=None) so having a form argument that I have, made it easy to fell into this trap. In my opinion, this is not well explained, and you have to dig into the code to understand that passing the form actually builds a Layout (maybe form_for_layout would be a better naming or simply adding form to the docstring - I created an issue with this suggestion, and will update this answer if it is implemented):

if form is not None:
    self.form = form
    self.layout = self.build_default_layout(form)

For someone new to django-crispy-forms (my case), this complicates things because it is actually defining the way the form fields are rendered. This is why adding the FormHelper after adding the field showed no problem (it added the field to the layout!), but doing it the other way around didn't work.

Understanding the problem was in layout led me to other solutions. If you need layout, form.helper.layout = form.helper.build_default_layout(form) (or del form.helper.layout) after adding the field also works, but you will lose any changes you made to the Layout.

Upvotes: 0

Related Questions