Tobi
Tobi

Reputation: 351

Django form fields depending on parameter with Crispy Forms

I am trying to have a Django Form (using Crispy form rendering), where the displayed form fields depend on a parameter passed to the Form from the view. I believe the parameter gets passed on correctly, but nonetheless, still all form fields are shown.

The model "IndividualFeedback" contains fields that can be used for a variety of different assessment types and has 8 fields for feedback categories. How many of those are displayed should depend on the assessment type that I specify in the views. I would like the "ESSAY" assessment type to display 4 of those category fields, and the "PRESENTATION" type to display 3. Currently, I get all 8 no matter what I pass on.

Here is my forms.py:

class IndividualFeedbackForm(forms.ModelForm):

    mark = forms.IntegerField() # One additional field that's not in the model
    helper = FormHelper()

    def __init__(self, *args, **kwargs):
        marksheet_type = kwargs.pop('marksheet_type')
        super(IndividualFeedbackForm, self).__init__(*args, **kwargs)

        helper = FormHelper()
        if marksheet_type == 'ESSAY':
            print('Detects marksheet') # Just for testing - and it does... 
            helper.layout = Layout(
                'marker',
                'marking_date',
                'submission_date',
                Field('category_mark_1', label=CATEGORIES['ESSAY']['i-1']),
                Field('category_mark_2', label=CATEGORIES['ESSAY']['i-2']),
                Field('category_mark_3', label=CATEGORIES['ESSAY']['i-3']),
                Field('category_mark_4', label=CATEGORIES['ESSAY']['i-4']),
                'comments',
                'mark'
            )
        elif marksheet_type == 'PRESENTATION':
            ...

    class Meta:
        model = IndividualFeedback
        fields = [
            'marker',
            'marking_date',
            'submission_date',
            'comments',
            'category_mark_1',
            'category_mark_2',
            'category_mark_3',
            'category_mark_4',
            'category_mark_5',
            'category_mark_6',
            'category_mark_7',
            'category_mark_8',
        ]

The code in the views.py is quite straight forward and obviously passes the right parameter on - as shown by the "print" line.

How can I get this to work?

And as a second question: is it enough for testing purposes to simply test "assertContains" in the form_as_p() or do I need something else because of Crispy Forms?

Upvotes: 0

Views: 2060

Answers (1)

dukebody
dukebody

Reputation: 7195

You are creating a variable named 'helper' but not assigning it to the form instance. You need to use self.helper = FormHelper:

def __init__(self, *args, **kwargs):
        marksheet_type = kwargs.pop('marksheet_type')
        super(IndividualFeedbackForm, self).__init__(*args, **kwargs)

        self.helper = FormHelper()
        if marksheet_type == 'ESSAY':
            print('Detects marksheet') # Just for testing - and it does... 
            self.helper.layout = Layout(
                'marker',
                'marking_date',
                'submission_date',
                Field('category_mark_1', label=CATEGORIES['ESSAY']['i-1']),
                Field('category_mark_2', label=CATEGORIES['ESSAY']['i-2']),
                Field('category_mark_3', label=CATEGORIES['ESSAY']['i-3']),
                Field('category_mark_4', label=CATEGORIES['ESSAY']['i-4']),
                'comments',
                'mark'
            )
        elif marksheet_type == 'PRESENTATION':
            ...

See example http://django-crispy-forms.readthedocs.org/en/latest/form_helper.html#formhelper-with-a-form-attached-default-layout .

You can also remove the FormHelper() from the class definition, at the top.

Finally, keep in mind that crispy forms will automatically append any fields defined in the form Meta class not present in the layout. See source.

Upvotes: 0

Related Questions