I am Trying To create a API for my custom user model to register a user and get details about current user that is logged in . I tried to Follow a tutorial but I faced 2 problems, 1.The confirmation password is not being hashed when creating a user, 2. The Get method didn't work ( I was Trying to Get User details Using the id, it didn't return any thing except bad request responce ). I hope any one can help me.
This is my models.py:
from django.db import models
from django import forms
# Create your models here.
from django.db import models
from django.contrib.auth.models import (
AbstractUser,
BaseUserManager,
AbstractBaseUser
)
from django.forms import Widget
from django.urls import reverse
class CustomUserManager(BaseUserManager):
def create_user(self,email,password=None,is_active=True,is_staff=False,is_admin=False):
if not email:
raise ValueError('User Must Have Email')
if not password:
raise ValueError('User Must Have Password')
user_obj = self.model(
email = self.normalize_email(email)
)
user_obj.set_password(password)#change user password
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self,email,password=None):
user = self.create_user(
email,
password = password,
is_staff = True
)
return user
def create_superuser(self,email,password=None):
user = self.create_user(
email,
password = password,
is_staff = True,
is_admin = True,
)
return user
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length= 200)
first_name = models.CharField(max_length = 300)
last_name = models.CharField(max_length = 300)
email = models.EmailField(max_length=255,unique=True)
password = models.CharField(max_length=100,)
password_2 = models.CharField(max_length=100,)
sub_to_newsletter = models.BooleanField(default=True)
own_pc = models.BooleanField(default=False)
active = models.BooleanField(default=True) #can login
staff = models.BooleanField(default=False) #staff user not superuser
admin = models.BooleanField(default=False) #admin / superuser
USERNAME_FIELD = 'email' #username
#email and password is requierd by default
REQUIRED_FIELDS = [] #python manage.py createsuperuser
objects = CustomUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def has_perm(self,perm,obj=None):
return True
def has_module_perms(self,app_label):
return True
@property
def is_staff(self):
return self.staff
@property
def is_admin(self):
return self.admin
@property
def is_active(self):
return self.active
def get_absolute_url(request):
return reverse('')
This is my forms.py:
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import ReadOnlyPasswordHashField
User = get_user_model()
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password = forms.CharField(widget=forms.PasswordInput())
password_2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput())
class Meta:
model = User
fields = ['email']
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
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ['email', 'password']
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
This is admin.py:
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import *
from .forms import *
User = get_user_model()
# Register your models here.
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ['email', 'admin']
list_filter = ['admin']
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('username','first_name','last_name','sub_to_newsletter','own_pc')}),
('Permissions', {'fields': ('admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password', 'password_2')}
),
)
search_fields = ['email']
ordering = ['email']
filter_horizontal = ()
admin.site.register(User,UserAdmin)
CodePudding user response:
I suggest that you remove password_2
from your user model. There is no reason to store the password twice. The purpose of a "confirm password" is to force the user to enter the same password twice in order to eliminate typos.
You can keep password_2
as a form field. Then add field validation to check that password
and password_2
are the same.