Reputation: 678
I am creating a system with Django. I already created a login page in the beginning of the project. But now, I realized that I have no conditions for password field. I want to put some restrictions like 8 characters, uppercase and lowercase letters and numbers. How can I check this when user fills the form?
forms.py
class SignUpForm(forms.ModelForm):
password1 = forms.CharField(max_length=250, min_length=8, widget=forms.PasswordInput)
password2 = forms.CharField(max_length=250, min_length=8, widget=forms.PasswordInput)
...
models.py
class UserProfile(AbstractUser, UserMixin):
...
last_name = models.CharField(max_length=200)
password = models.CharField(max_length=250)
views.py
def signup(request):
current_user = request.user
new_user = UserProfile(company=current_user.company)
form = SignUpForm(request.POST or None, user=request.user, instance=new_user)
rank_list = Rank.objects.filter(company=current_user.company)
if request.method == 'POST':
if form.is_valid():
form.instance.username = request.POST.get('email', None)
new_user = form.save()
...
}
return render(request, 'signup.html', context)
EDIT
I added codes according to the answers but It did not works.
settings.py
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 12, }
},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', },
{'NAME': 'register.validators.UppercaseValidator', },
{'NAME': 'register.validators.NumberValidator', },
{'NAME': 'register.validators.LowercaseValidator', },
]
register/validators.py
import re
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
class NumberValidator(object):
def __init__(self, min_digits=0):
self.min_digits = min_digits
def validate(self, password, user=None):
if not len(re.findall('\d', password)) >= self.min_digits:
raise ValidationError(
_("The password must contain at least %(min_digits)d digit(s), 0-9."),
code='password_no_number',
params={'min_digits': self.min_digits},
)
def get_help_text(self):
return _(
"Your password must contain at least %(min_digits)d digit(s), 0-9." % {'min_digits': self.min_digits}
)
class UppercaseValidator(object):
def validate(self, password, user=None):
if not re.findall('[A-Z]', password):
raise ValidationError(
_("The password must contain at least 1 uppercase letter, A-Z."),
code='password_no_upper',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 uppercase letter, A-Z."
)
class LowercaseValidator:
def validate(self, password, user=None):
if not re.findall('[a-z]', password):
raise ValidationError(
_("The password must contain at least 1 lowercase letter, a-z."),
code='password_no_lower',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 lowercase letter, a-z."
)
Upvotes: 2
Views: 2158
Reputation: 678
I am edited my forms.py like this. I use my customer signup form. and this is work for me:
class SignUpForm(forms.ModelForm):
password1 = forms.CharField(max_length=250, min_length=8, widget=forms.PasswordInput)
password2 = forms.CharField(max_length=250, min_length=8, widget=forms.PasswordInput)
class Meta:
model = UserProfile
fields = (
'first_name', 'last_name', 'email', 'password1', 'password2', 'rank', 'image')
labels = {
'email': 'E-mail',
'password1': 'Please Generate A Strong Password',
'password2': 'Please Confirm the Password',
'rank': 'Position'
}
widgets = {
'password1': forms.PasswordInput(),
'password2': forms.PasswordInput(),
}
def __init__(self, *args, **kwargs):
# using kwargs
user = kwargs.pop('user', None)
super(SignUpForm, self).__init__(*args, **kwargs)
self.fields['rank'].queryset = Rank.objects.filter(company=user.company)
self.fields['password1'].label = 'Please Generate A Strong Password'
self.fields['password2'].label = 'Please Confirm the Password'
def clean(self):
cleaned_data = super(SignUpForm, self).clean()
password = cleaned_data.get('password1')
# check for min length
min_length = 8
if len(password) < min_length:
msg = 'Password must be at least %s characters long.' % (str(min_length))
self.add_error('password1', msg)
# check for digit
if sum(c.isdigit() for c in password) < 1:
msg = 'Password must contain at least 1 number.'
self.add_error('password1', msg)
# check for uppercase letter
if not any(c.isupper() for c in password):
msg = 'Password must contain at least 1 uppercase letter.'
self.add_error('password1', msg)
# check for lowercase letter
if not any(c.islower() for c in password):
msg = 'Password must contain at least 1 lowercase letter.'
self.add_error('password1', msg)
password_confirm = cleaned_data.get('password2')
if password and password_confirm:
if password != password_confirm:
msg = "The two password fields must match."
self.add_error('password2', msg)
return cleaned_data
Upvotes: 0
Reputation: 179
Django includes some basic validators (docs)
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 9,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
But you can create your own validators:
In your app, create validators.py
And add your validations classes there (docs)
# EX Validation for uppercase
class UppercaseValidator(object):
def validate(self, password, user=None):
if not re.findall('[A-Z]', password):
raise ValidationError(
_("The password must contain at least 1 uppercase letter, A-Z."),
code='password_no_upper',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 uppercase letter, A-Z."
)
Finally update the AUTH_PASSWORD_VALIDATORS setting with the path to your validators
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 12, }
},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', },
{'NAME': 'myproject.validators.UppercaseValidator', },
]
Upvotes: 2
Reputation: 64
Check this: https://sixfeetup.com/blog/custom-password-validators-in-django
If you have more specific needs, you can create your own validators. To do so, simply create your own classes based on object and raise a ValidationError if the entered password fails.
Upvotes: 1