Search code examples
pythondjangobootstrap-4django-widget

Django Widgets with Bootstrap


I am trying to stylize my form using bootstrap. As you know bootstrap uses a lot of classes in order to do what it does. By googling I have found to inject some new classes into my form I could use widgets with django. My form is as follows:

class SignUpForm(UserCreationForm):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    email = forms.EmailField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['password1'].label = 'Password'
        self.fields['password2'].label = 'Password Confirmation'
        self.fields['first_name'].label = 'First Name'
        self.fields['last_name'].label = 'Last Name'

        self.fields['password1'].help_text = None
        self.fields['password2'].help_text = None

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2' )
        help_texts = {
            'username': None,
        }
        widgets = {
            'username': forms.TextInput(
                attrs={
                    'class': 'form-control'
                }
            ),
            'first_name': forms.TextInput(
                attrs={
                    'class': 'form-control'
                }
            ),
            'last_name': forms.TextInput(
                attrs={
                    'class': 'form-control'
                }
            ),
            'email': forms.EmailInput(
                attrs={
                    'class': 'form-control'
                }
            ),
            'password1': forms.PasswordInput(
                attrs={
                    'class': 'form-control'
                }
            ),
            'password2': forms.PasswordInput(
                attrs={
                    'class': 'form-control'
                }
            )
        }

But for some reason this is only applying the class to the username field in HTML. It does not apply the class 'form-control' to anything else. Is this some simple format issue I am overlooking or am I doing something wrong? Any help is greatly appreciated!


Solution

  • Meta.widgets only applies to the automatically created form fields. If you are manually creating some of them, you need to specify your widgets there.

    class SignUpForm(UserCreationForm):
        first_name = forms.CharField(max_length=30, widget=forms.TextInput(
            attrs={
                'class': 'form-control'
            }
        ))
        last_name = forms.CharField(max_length=30, widget=forms.TextInput(
            attrs={
                'class': 'form-control'
            }
        ))
        email = forms.EmailField(widget=forms.EmailInput(
            attrs={
                'class': 'form-control'
            }
        ))
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['password1'].label = 'Password'
            self.fields['password2'].label = 'Password Confirmation'
            self.fields['first_name'].label = 'First Name'
            self.fields['last_name'].label = 'Last Name'
    
            self.fields['password1'].help_text = None
            self.fields['password2'].help_text = None
    
        class Meta:
            model = User
            fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2' )
            help_texts = {
                'username': None,
            }
            widgets = {
                'username': forms.TextInput(
                    attrs={
                        'class': 'form-control'
                    }
                ),
                'password1': forms.PasswordInput(
                    attrs={
                        'class': 'form-control'
                    }
                ),
                'password2': forms.PasswordInput(
                    attrs={
                        'class': 'form-control'
                    }
                )
            }
    

    This explains the situation only for the first_name, last_name and email. For the password1 and password2 the situation is actually the same, but it's a bit obscured, as those fields are manually defined in your parent class, UserCreationForm. You need to define them again to change the widget. Alternatively, you can overwrite the widgets in __init__ of your form class.