Overriding the default class attribute using django-crispy-forms

Question:

I am currently learning how to use django crispy forms and can’t figure out this issue. I am using it alongside bootstrap5.

I have the following form :

class CommentForm(forms.ModelForm):
    class Meta : 
        model = Comments
        fields = ["comment_content"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_show_labels = False
        self.fields['comment_content'].widget.attrs['placeholder'] = 'comment here...'
        self.helper.layout = Layout(
            "comment_content",
        )
        self.helper.layout.append(Submit("post_comment", "Post comment",css_class="btn btn-outline-primary"))

The issue is with the last line : instead of replacing the default class (btn btn-primary) by the value of css_class,it simply adds this value afterwards so the resulting html is the following :

<input type="submit" name="post_comment" value="Post comment" class="btn btn-primary btn-outline-primary" id="submit-id-post_comment">

How do I make it so the resulting class is "btn btn-outline-primary" and not "btn btn-primary btn-outline-primary"?

Asked By: WalterBlack1

||

Answers:

Reading the Submit class documentation (https://django-crispy-forms.readthedocs.io/en/latest/api_layout.html#layout.Submit), we see :

css_classstr, optional

Additional CSS classes to be applied to the input. By default None

This means that the string provided to css_class won’t override the default value, it will simply add to it.

To find the default value, we need to look at the source code for the Submit class (https://django-crispy-forms.readthedocs.io/en/latest/_modules/layout.html) we see the following :

class Submit(BaseInput):
    input_type = "submit"
    field_classes = "btn btn-primary"

We can then create custom buttons by replicating the same code structure :

class CustomSubmit(BaseInput):
    input_type = "submit"
    field_classes = "btn btn-outline-primary"

I was then able to fix the problematic line as such :
self.helper.layout.append(CustomSubmit("post_comment", "Post comment",))

The resulting html now corresponding to the bootstrap outlined class :
<input type="submit" name="post_comment" value="Outlined comment button" class="btn btn-outline-primary" id="submit-id-post_comment">

Answered By: WalterBlack1

After analyzing the source code of the crispy-form layout with bootstrap5(exacttly Submit element), it seems like default css class is btn btn-primary (from source code):

class Submit(BaseInput):  
    # ...
    input_type = "submit"
    field_classes = "btn btn-primary"

So you can modify your code little bit as below:

    # ...
    self.helper.layout = Layout(
            "comment_content",
    )
    _submit = Submit("post_comment", "Post comment")
    _submit.field_classes = 'btn btn-outlined-primary '
    self.helper.layout.append(_submit)
Answered By: Shekhrox