Reputation: 2022
I am trying to create form for user registration and add some custom fields. For doing that, I've subclassed UserCretionForm and added fields as shown in django documentation. Then I've created function-based view and template based on this form. Now, I can successfully create user and this user is added to admin panel as expected. Problem is that, I can't add class and style for this form's fields. Widgets are not working except for username field. I'm adding my scripts here for illustrating my problem more accurately:
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=32, help_text='First name')
last_name = forms.CharField(max_length=32, help_text='Last name')
email = forms.EmailField(max_length=64, help_text='Enter a valid email address')
class Meta(UserCreationForm.Meta):
model = User
# I've tried both of these 'fields' declaration, result is the same
# fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )
fields = UserCreationForm.Meta.fields + ('first_name', 'last_name', 'email',)
widgets = {
'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Username'}),
'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}),
'last_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Last Name'}),
'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}),
'password1': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password'}),
'password2': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password Again'}),
}
views.py
from django.contrib.auth import login, authenticate
from django.contrib.auth.views import LoginView
from django.shortcuts import render, redirect
from .forms import SignUpForm, SignInForm
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('/')
else:
form = SignUpForm()
return render
Widgets in 'forms.py' are not working except for 'username' field. In other words, in web browser 'username' input is shown with "class='form-control'" and "placeholder='Username'", but other fields don't have class and placeholder attribute as I expected. What can be the reason?
Upvotes: 7
Views: 23931
Reputation: 552
Just need to add a note on @Chirdeep answer, if you tried to render the form you would lose the field.help_text for the password.
In order to fix, we can re-write the forms as below
please note to import the password_validation
from django.contrib.auth
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import password_validation
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.validators import UnicodeUsernameValidator
username_validator = UnicodeUsernameValidator()
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=12, min_length=4, required=True, help_text='Required: First Name',
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}))
last_name = forms.CharField(max_length=12, min_length=4, required=True, help_text='Required: Last Name',
widget=(forms.TextInput(attrs={'class': 'form-control'})))
email = forms.EmailField(max_length=50, help_text='Required. Inform a valid email address.',
widget=(forms.TextInput(attrs={'class': 'form-control'})))
password1 = forms.CharField(label=_('Password'),
widget=(forms.PasswordInput(attrs={'class': 'form-control'})),
help_text=password_validation.password_validators_help_text_html())
password2 = forms.CharField(label=_('Password Confirmation'), widget=forms.PasswordInput(attrs={'class': 'form-control'}),
help_text=_('Just Enter the same password, for confirmation'))
username = forms.CharField(
label=_('Username'),
max_length=150,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator],
error_messages={'unique': _("A user with that username already exists.")},
widget=forms.TextInput(attrs={'class': 'form-control'})
)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2',)
Upvotes: 2
Reputation: 4461
You don't need to define fields unders widgets. Define them as static at class level.
class SignUpForm(UserCreationForm):
username = forms.CharField(forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Username'}))
first_name = forms.CharField(forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}), max_length=32, help_text='First name')
last_name=forms.CharField(forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Last Name'}), max_length=32, help_text='Last name')
email=forms.EmailField(forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}), max_length=64, help_text='Enter a valid email address')
password1=forms.CharField(forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password'}))
password2=forms.CharField(forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password Again'}))
class Meta(UserCreationForm.Meta):
model = User
# I've tried both of these 'fields' declaration, result is the same
# fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )
fields = UserCreationForm.Meta.fields + ('first_name', 'last_name', 'email',)
Upvotes: 10