0

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!

mharre
  • 233
  • 3
  • 17

1 Answers1

3

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.

GwynBleidD
  • 20,081
  • 5
  • 46
  • 77
  • Oh wow thank you for that information, I had no idea as I am still pretty new to django. I will definitely try all of these, as you mentioned the password ones may be more difficult due to them being manually defined. I will try to figure it out with some more googling if I can't figure it out on my own! – mharre Jun 15 '21 at 10:14
  • Actually quick question that I forgot to mention in my reply, when you say I need to define them again to change the widget what do you mean exactly? As I am using django to create the form for me based on UserCreationForm and also basing it off of the User model that django creates as well. – mharre Jun 15 '21 at 10:33
  • Well I also managed to do it the other way you mentioned by overwriting the __init__ for my form class like so: `self.fields['password1'].widget = forms.widgets.PasswordInput(attrs={'class': 'form-control'}) self.fields['password2'].widget = forms.widgets.PasswordInput(attrs={'class': 'form-control'})` Sorry for the format I am unsure how to post code in comments. Being relatively new to programming is there any negatives to using this __init__ overwrite way? Would it be considered bad practice? – mharre Jun 15 '21 at 10:38