Django modelform how to add a confirm password field? - python-3.x

Here I need to add an extra confirmation password in my form.I used Django's modelform. I also need to validate both passwords. It must raise a validation error if password1 != password2.
Here is my forms.py:
class UserForm(forms.ModelForm):
password=forms.CharField(widget=forms.PasswordInput())
class Meta:
model=User
fields=('username','email','password')
class UserProfileForm(forms.ModelForm):
YESNO_CHOICES = (('male', 'male'), ('female', 'female'))
sex = forms.TypedChoiceField(choices=YESNO_CHOICES, widget=forms.RadioSelect)
FAVORITE_COLORS_CHOICES=(('red','red'),('blue','blue'))
favorite_colors = forms.MultipleChoiceField(required=False,widget=forms.CheckboxSelectMultiple, choices=FAVORITE_COLORS_CHOICES)
dob = forms.DateField(widget=forms.DateInput(format = '%d/%m/%Y'),
input_formats=('%d/%m/%Y',))
class Meta:
model=UserProfile
fields=('phone','picture','sex','favorite_colors','dob')
And here is my registration function:
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
registered = True
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request,
'mysite/register.html',
{'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )

Use clean like
class UserForm(forms.ModelForm):
password=forms.CharField(widget=forms.PasswordInput())
confirm_password=forms.CharField(widget=forms.PasswordInput())
class Meta:
model=User
fields=('username','email','password')
def clean(self):
cleaned_data = super(UserForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)

def clean(self):
cleaned_data = super(UserAccountForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
self.add_error('confirm_password', "Password does not match")
return cleaned_data

Try this for forms.py:
class UserForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput())
password_confirm = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields=('username','email','password')
And this in views.py:
if user_form.is_valid() and profile_form.is_valid() and user_form.cleaned_data['password'] == user_form.cleaned_data['password_confirm']:
...
elif user_form.data['password'] != user_form.data['password_confirm']:
user_form.add_error('password_confirm', 'The passwords do not match')

You can have a look at how Django does it for UserCreationForm.
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
Here password2 refers to the confirm_password field, under the assumption that it appears after the password field. Trying to use the same implementation for clean_password may lead to an error that the confirm_password data wasn't found.
This has the advantage that you're raising the error for a particular Field, instead of the whole form, which you can then render appropriately in your template.
However, if you're trying to validate data across multiple fields, the documentation advises overriding the clean() method, as answered by Savai.
The source code is available here.

Confirm password is already available in UserCreationForm
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
This will automatically verify password1==password2 when form.is_valid() is called.
Here I am only taking email as a separate form arguments for further clean up and validation

Related

The serializer always return none. Why?

The serializer always return none. Why?? Creating custom models time?
File views.py
print password = None
class UserLoginView(APIView):
def post(self, request, format=None):
serializer = UserLoginSerializer(data=request.data,)
if serializer.is_valid(raise_exception=True):
email = serializer.data.get('email')
password = serializer.data.get('password')
**print(password)**
print(request.data)
print(serializer.data)
user = authenticate(email=email, password=password)
print(user)
return Response({'msg':'successful login'}, status=status.HTTP_200_OK)
File Serializer.py
class UserLoginSerializer(serializers.ModelSerializer):
email = serializers.EmailField(max_length=255)
class Meta:
model = User
fields = ['email', 'password',]
extra_kwargs={
'password':{'write_only': True},
}
File Models.py
class UserManager(BaseUserManager):
def create_user(self, email, number, name, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
if not number:
raise ValueError('Users must have an email address')
user = self.model(
email = self.normalize_email(email),
number = number,
name = name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, number, name, password=None):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
number = number,
password = password,
name = name,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
number=models.CharField(max_length=10)
name=models.CharField(max_length=30)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name','number']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return self.is_admin
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Output
Quit the server with Ctrl + Break.
**None**
{'email': 'g#gmail.com', 'password': '123'}
{'email': 'g#gmail.com'}
**None**
\[06/Feb/2023 18:53:52\] "POST /api/user/login/ HTTP/1.1" 200 26**your text**
Try this:
email=serializer.data['email']
password=serializer.data['password']

Django - How to Manually update/set/Reset password

I tried to reset password manually by passing key But it always says
AttributeError : 'str' object has no attribute 'get'
I googled many times even if i saw Manual Password with hiding password field Django but no luck favor me.
// In my form #forms.py
class UserResetPasswordForm(forms.Form):
new_password1 = forms.CharField(
label=_("New Password"),
widget=forms.PasswordInput(attrs={"autocomplete":"off"}),
strip=False,
help_text=password_validation.password_validators_help_text_html(),
)
new_password2 = forms.CharField(
label=_("New Password Confirmation"),
strip=False,
widget=forms.PasswordInput(attrs={"autocomplete":"off"}),
)
In Url
path('password-reset/confirm/<str:reg_key>/', accounts_view.myreset_password_confirm, name='myreset_password_confirm'),
In View #views.py
def myreset_password_confirm(request, reg_key):
user = User.objects.filter(activate_key=reg_key).first()
if user is not None:
if request.method == 'POST':
form = UserResetPasswordForm(request.POST)
if form.is_valid():
#password1 = form.cleaned_data.get('new_password1')
#password2 = form.cleaned_data.get('new_password2')
password1 = request.POST['new_password1']
password2 = request.POST['new_password2']
if password1 and password2:
if password1 != password2:
raise ValidationError("Your password didn't match.")
password_validation.password_validators_help_text_html()
return password2
print(password2)
user.activate_key = ''
user.set_password(password2)
user.save()
print("Print User")
print(type(user))
messages.success(request, f"Your password for {user.email} has been reset successfully!")
return HttpResponseRedirect('/')
else:
form = UserResetPasswordForm()
return render(request, 'reset_password_confirm.html', {'form':form})
else:
print("U R Boomed")
messages.error(request, "Your requested URL is not Valid, Please try with valid URL.")
return HttpResponseRedirect('/')
Please help, how to solve it?
You are returning return password2, which is not proper HttpResonse. I don't think you wanted to do that. Just delete this line.

Custom User Model with multiple Unique id - Django RestFramework

Hi StackOverFlow buddies,
I have created a custom User model for my project and would like to register the Users with Restframework.
I want Custom User model to have 2 unique fields together, for which I followed "Official doc" for unique_together property. It seems to be only taking only 1 field (ie email for my case), as a unique one.
Relevant piece my code until this point looks like this:
PS: Let me know if more info is required.
models.py
class MasterUser(AbstractBaseUser):
email = models.EmailField(verbose_name='email address',max_length=255,unique=True,)
firstname = models.CharField(max_length=100,blank=True)
contact = models.CharField(max_length=100, blank=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname']
class Meta:
unique_together = (('email', 'contact'),)
serializer.py
class RegisterUserSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type': 'password'}, write_only= True)
class Meta:
model = MasterUser
fields = ('firstname', 'password', 'password2', 'email','contact')
extra_kwargs = {
'password': {'write_only': True},
}
def save(self):
account = MasterUser(
email = self.validated_data['email'],
firstname = self.validated_data['firstname'],
contact = self.validated_data['contact'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Password doesnt matches'})
account.set_password(password)
account.save()
return account
views.py
#api_view(['POST'])
def registration_view(request):
if request.method == "POST":
serializer = RegisterUserSerializer(data= request.data)
data = {}
if serializer.is_valid():
account = serializer.save()
data['response'] = "Successfully registered new user!"
else:
data = serializer.errors
return Response(data)
Where am I missing to implement thing?
unique_together means the set of fields you defined should be unique for all Users. If you also want contact to be a unique field when stored in db, you should pass the unique parameter like so:
class MasterUser(AbstractBaseUser):
...
contact = models.CharField(max_length=100, blank=True, unique=True)
...

Django PostgreSQL - the password isn't saved to the database

I have a custom User model and a function in views.py to handle the registration. when I register a user with Postman for example all the user data is stored in the database correctly but the password -field remains empty. I think that causes the problem when I try to use a simple login -page - it never accepts my credentials (because there is no password in the database). Any ideas why the password isn't saved and how to fix it?
I have a function like this in views.py when registering a new user:
def register(response):
if response.method == 'POST':
form = RegisterForm(response.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.id = form.cleaned_data.get('id')
user.save()
username = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
user = authenticate(username=email, password=password)
return HttpResponse(status=201)
else:
form = RegisterForm()
return HttpResponse(status=400)
And this is my custom user model:
class UserManager(BaseUserManager):
def create_user(self, email, password):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('A user must have a email.')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
Edit. Here is my RegisterForm:
User = get_user_model()
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password_2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email', 'id', 'gender', 'height', 'weight']
def clean_email(self):
'''
Verify email is available.
'''
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_id(self):
'''
Verify id is available.
'''
id = self.cleaned_data.get('id')
qs = User.objects.filter(id=id)
if qs.exists():
raise forms.ValidationError("id is taken")
return id
def clean(self):
'''
Verify both passwords match.
'''
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_2 = cleaned_data.get("password_2")
if password is not None and password != password_2:
self.add_error("password_2", "Your passwords must match")
return cleaned_data
And here is the model:
class CustomUser(AbstractBaseUser):
is_active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
gender = models.CharField(null=True, blank=True, max_length=20)
height = models.CharField(null=True, blank=True, max_length=3)
id = models.CharField(primary_key=True, unique=True, blank=False, max_length=100)
email= models.EmailField(max_length=100, unique=True, null=False, blank=False)
weight = models.CharField(max_length=3, null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Email & Password are required by default.
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
return self.staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.admin
objects = UserManager()
And soon after editing my question I noticed I was missing the save function from the RegisterForm class. Adding this solved the problem:
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user

How to Allow Superusers to access Django Admin Panels

I have the below code for Custom Users Model.
Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
# UserManager is for Custom User Model to override Django's Default Model
class UserManager(BaseUserManager):
def _create_user(self, email, password, is_superuser, **extra_fields):
if not email or not password:
raise ValueError("The given username or password must not be null")
user = self.model(
email=email,
password=password,
is_superuser=is_superuser,
last_login=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
return self._create_user(email, password, False, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
return self._create_user(email, password, True, **extra_fields)
class Users(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
created_at_utc = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['password']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return self.is_admin
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
class Meta:
db_table = "users"
I have the above code for Users, and following Code for Admin Panel to create and update User's
Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
class UserCreateForm(UserCreationForm):
class Meta:
model = Users
fields = (
"email","is_admin","is_superuser",
)
class UserChangeForm(BaseUserChangeForm):
class Meta:
model = Users
fields = (
"email","is_admin",
)
class UserAdmin(BaseAdmin):
form = UserChangeForm
add_form = UserCreateForm
fieldsets = (
(None, {"fields": ("email", "password","is_active","is_admin","is_superuser")}),
)
add_fieldsets = (
(None, {
"classes": ("wide",),
"fields": ("email", "password1", "password2","is_active","is_admin","is_superuser")}
),
)
filter_horizontal = ()
list_display = ("email","is_active", )
list_filter = ("is_active", )
search_fields = ("email",)
ordering = ("email",)
# Register your models here.
admin.site.register(Users, UserAdmin)
I have tried many solutions to restrict only SuperUser's to access the Admin Page when Login details are given. Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
I think what you are looking for field is is_staff which is there in
class AbstractUser(AbstractBaseUser, PermissionsMixin):
you can import this user from
from django.contrib.auth.models import AbstractUser
and you will find that it has field named as is_staff, so this is basically boolean field which determines if user has access to login to admin site or not, for more info do google search or find the article below
https://www.webforefront.com/django/adminpermissions.html
I see that you have created function as def is_staff(self): but you are not using field is_staff
Had the same issue. Instead of password=None, change it to password. And pass password=password into the create_user function as you see below, together with username=username:
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password):
if not email:
raise ValueError('Please add an email address')
if not username:
raise ValueError('Please add an username')
user = self.model(email=self.normalize_email(
email), username=username, password=password)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(email=self.normalize_email(
email), username=username, password=password)
user.is_active = True
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
Hope it works for you

Resources