Django-rest-auth (dj-rest-auth) custom user registration - django

I'm using dj-rest-auth (https://dj-rest-auth.readthedocs.io/en/latest/) and trying to implement a custom registration form. When I'm trying to register a new user I have the base form.
I've seen with the older version (https://django-rest-auth.readthedocs.io/en/latest/) that if you use password1 and password2, you don't have to retype all the code.
serializers.py
from rest_framework import serializers
from dj_rest_auth.registration.serializers import RegisterSerializer
class CustomRegisterSerializer(RegisterSerializer):
first_name = serializers.CharField()
last_name = serializers.CharField()
def get_cleaned_data(self):
super(CustomRegisterSerializer, self).get_cleaned_data()
return {
'username': self.validated_data.get('username', ''),
'password1': self.validated_data.get('password1', ''),
'password2': self.validated_data.get('password2', ''),
'email': self.validated_data.get('email', ''),
'first_name': self.validated_data.get('first_name', ''),
'last_name': self.validated_data.get('last_name', '')
}
settings.py
REST_AUTH_SERIALIZERS = {
'REGISTER_SERIALIZER': 'accounts.serializers.CustomRegisterSerializer',
}

The problem was in settings.py:
REST_AUTH_REGISTER_SERIALIZERS = {
'REGISTER_SERIALIZER': 'accounts.serializers.CustomRegisterSerializer'
}

You can create your own User and make it the AUTH_USER_MODEL of your project with something like this:
from django.contrib.auth.models import AbstractUser, BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, email, username,first_name, last_name, password=None):
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email, username, password, first_name, last_name, is_tutor, is_student):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
first_name=first_name,
last_name=last_name,
)
user.is_staff = True
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
rating = models.FloatField(default=0, blank=True, null=True)
reviews_count = models.IntegerField(default=0)
first_name = models.CharField(verbose_name='first_name', max_length=30)
last_name = models.CharField(verbose_name='last_name', max_length=30)
USERNAME_FIELD = 'email'
#this field means that when you try to sign in the username field will be the email
#change it to whatever you want django to see as the username when authenticating the user
REQUIRED_FIELDS = ['username', 'first_name', 'last_name',]
objects = MyUserManager()
def __str__(self):
return self.first_name + ' - ' + self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
Then in settings.py you declare the AUTH_USER_MODEL = "to the model you just created" and in serializers.py create a serializer for the user registration:
class UserRegistrationSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type':'password'}, write_only=True)
class Meta:
model = User
fields = ['username', 'email', 'first_name','last_name',
'password', 'password2',]
extra_kwargs = {
'password': {
'write_only':True
}
}
def save(self):
user = User(
email=self.validated_data['email'],
username=self.validated_data['username'],
first_name=self.validated_data['first_name'],
last_name=self.validated_data['last_name'],
is_tutor=self.validated_data['is_tutor'],
is_student=self.validated_data['is_student'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password':'Passwords must match.'})
user.set_password(password)
user.save()
return user
then you register your custom user model in the django admin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
class AccountAdmin(UserAdmin):
list_display = ('email', 'username','pk', 'date_joined', 'last_login', 'is_admin', 'is_staff')
search_fields = ('email', 'username')
readonly_fields = ('date_joined', 'last_login')
filter_horizontal = ()
list_filter = ()
fieldsets = ()
admin.site.register(User, AccountAdmin)
I hope this helps or at least point you in the right direction to where you want to be

Related

Not hashing password. Unexpected keyword argument 'password2'

I have three different questions. They're all related to each other.
1 - I get an error when I add password2 or confirm_password field.
Got a `TypeError` when calling `CustomUser.objects.create()`.
This may be because you have a writable field on the serializer class that is not a valid argument to `CustomUser.objects.create()`.
You may need to make the field read-only, or override the UserCreateSerializer.create() method to handle this correctly.
TypeError: CustomUser() got an unexpected keyword argument 'confirm_password'
2 - Without any validate when I only have password field. I am not getting any errors but passwords are not hashed.
3 - When I want to create user using shell. Even if I leave all the fields blank, I can create an empty user without any errors.
Custom User Manager
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None,**kwargs):
if not email:
raise ValueError('Email is required!')
user = self.model(
email = self.normalize_email(email),
**kwargs,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **kwargs):
user = self.create_user(
email,
password=password,
**kwargs
)
user.is_admin = True
user.save(using=self._db)
return user
Custom User
class CustomUser(AbstractBaseUser):
email = models.EmailField(_('Email'), max_length=50, unique=True)
username = models.CharField(_('Username'),max_length=50)
first_name = models.CharField(_('First Name'),max_length=50)
middle_name = models.CharField(_('Middle Name'),max_length=50, blank=True, null=True)
last_name = models.CharField(_('Last Name'),max_length=50)
desc = models.TextField(_('Description'), blank=True, default='Nothing here.')
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(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):
"Is the user a member of staff?"
return self.is_admin
User Serializer
User = get_user_model()
class UserCreateSerializer(serializers.ModelSerializer):
email = serializers.EmailField(required=True, validators =[validators.UniqueValidator(queryset=User.objects.all())])
password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
confirm_password = serializers.CharField(write_only=True, required=True)
class Meta:
model = User
fields = [
'email',
'username',
'first_name',
'middle_name',
'last_name',
'password',
'confirm_password',
]
def validate(self, data):
email = data['email']
print(data)
user_qs = User.objects.filter(email=email)
if user_qs.exists():
raise serializers.ValidationError('This user has already registered!')
if data['password'] != data['confirm_password']:
raise serializers.ValidationError('Passwords didn\'t match!')
elif data.get('password') == data.get('confirm_password'):
data['password'] = make_password(
data.get('password')
)
data.pop('confirm_password', None)
return data
def create(self, validated_data):
username = validated_data['username']
email = validated_data['email']
first_name = validated_data['first_name']
middle_name = validated_data['middle_name']
last_name = validated_data['last_name']
user = User.objects.create(
username = username,
email = email,
first_name=first_name,
middle_name=middle_name,
last_name=last_name,
)
user.set_password(validated_data['password'])
user.save()
return user

Django Rest Framework API sets image to default image even if user uploads an image

When I try to create a new user through DRF, the avatar field displays the default image even if the user uploads an image. When I try to create a user with an image through the admin panel it works fine. So I'm assuming that I'm missing something in my serializer.
Custom User Model
class myAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError('Users must have an email')
if not username:
raise ValueError('Users must have an username')
user = self.model(
email = self.normalize_email(email),
username=username,
)
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),
password=password,
username=username,
)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
avatar = models.ImageField(default='default.jpg')
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now_add=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = myAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
User serializer
UserModel = User
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user = UserModel.objects.create_user(
username=validated_data['username'],
password=validated_data['password'],
email=validated_data['email'],
)
return user
class Meta:
model = UserModel
# Tuple of serialized model fields (see link [2])
fields = ( "id", "email", "username", "password", "avatar")
Static file path
STATIC_URL = '/static/'
MEDIA_URL = '/images/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
MEDIA_ROOT = BASE_DIR /'static/images'
The issue is with the serializer's create() method. You were not passing the avatar data into the create_user(...) method. So, update your method as below,
from rest_framework import serializers
UserModel = User
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
return UserModel.objects.create_user(**validated_data)
class Meta:
model = UserModel
# Tuple of serialized model fields (see link [2])
fields = ("id", "email", "username", "password", "avatar")

Include auto increment field to JSON response

New to Django and Django Rest.
I am looking to modify the JSON return response of my view so that it also returns the id of the created user.
The things is, the id is an auto increment integer and so I don't know how I can retrieve the info to add it to the JSON.
Any help would be appreciated.
Thanks.
models.py
class CustomUsers(AbstractUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=100)
USERNAME_FIELD = 'email'
class Meta:
db_table = "custom_users"
serializers.py
class CustomUsersCreateSerializer(serializers.ModelSerializer):
def create(self, validated_data):
last_name = validated_data['last_name']
first_name = validated_data['first_name']
username = validated_data['username']
email = validated_data['email']
password = validated_data['password']
user_obj = USER(
last_name=last_name,
first_name=first_name,
username=username,
email=email,
)
user_obj.set_password(password)
user_obj.save()
return validated_data
class Meta:
model = USER
fields = ('id', 'last_name', 'first_name', 'username', 'password', 'email')
extra_kwargs = {'password': {'write_only': True, 'min_length': 10}}
views.py
class UserCreateAPIView(CreateAPIView):
serializer_class = serializers.CustomUsersCreateSerializer
queryset = CustomUsers.objects.all()
I usually use Model.objects.create() to add new record but i think it's the same as your way of using save() so you can get created user id after save:
def create(self, validated_data):
last_name = validated_data['last_name']
first_name = validated_data['first_name']
username = validated_data['username']
email = validated_data['email']
password = validated_data['password']
user_obj = User.objects.create(
last_name=last_name,
first_name=first_name,
username=username,
email=email,
)
user_obj.set_password(password)
user_obj.save()
validated_data['user_id'] = user_obj.id
return validated_data

How to make Vue.js post hashed password to Django REST API AbstractBaseUser custom model?

I'm struggling to create users by sending data from Vue.js to Django REST Framework.
First of all, I made my own custom user model with AbstractBaseUser.
and migration where successful, It is able to communicate with mysql, vue.js too.
the python manage.py createsuperuser works well too.
So the password field created as hashed string automatically whenever I try to use createsupersuser and at the ~/admin domain too.
However when I'm trying to send POST method in Vue.js to user model,
It's just putted raw(non hashed) password in it, and not follow my Django default model set up like is_admin = False, is_active = True.
These boolean fields would be set always 'False' by Vue axios method
Here is my user model.
./Users/models.py
# Abstracted User fields with options
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(
max_length=20,
null=False,
blank=False,
unique=True,
error_messages={'unique': _('이미 존재하는 아이디 입니다. (The account is already existed.)')},
)
full_name = models.CharField(
_('first_name' + 'last_name'),
max_length=30,
default='',
)
email = models.EmailField(
_('email address'),
)
organization = models.CharField(
max_length=50,
null=True,
blank=True,
)
phone = models.CharField(
max_length=16,
null=True,
blank=True,
)
is_staff = models.BooleanField(
_('is_staff'),
default=False,
)
is_active = models.BooleanField(
_('is_active'),
default=True,
)
created_date = models.DateTimeField(
_('date joined'),
auto_now_add=True,
)
updated_date = models.DateTimeField(
auto_now=True,
)
# User Management object
objects = UserManager()
# This field will be the 'username'
USERNAME_FIELD = 'username'
# Required for create user (without username, password)
REQUIRED_FIELDS = ['full_name', 'email', 'organization', 'phone']
class Meta:
db_table = 'Users'
verbose_name = _('user')
verbose_name_plural = _('users')
def __str__(self):
return self.username
def get_full_name(self):
"""
This method is required by Django for things like handling emails.
Typically this would be the user's first and last name. Since we do
not store the user's real name, we return their username instead.
"""
if self.full_name:
return self.full_name
return self.email
def get_short_name(self):
"""
This method is required by Django for things like handling emails.
Typically, this would be the user's first name. Since we do not store
the user's real name, we return their username instead.
"""
if self.full_name:
return self.full_name
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def token(self):
return self._generate_jwt_token()
def _generate_jwt_token(self):
dt = datetime.now() + timedelta(days=1)
token = jwt.encode({
'id': self.pk,
'exp': int(dt.strftime('%s'))
}, settings.SECRET_KEY, algorithm='HS256')
return token.decode('utf-8')
And it is my user manager. in same repository.
# Abstracted User manager.
class UserManager(BaseUserManager):
def create_user(self, username, password=None, full_name=None, organization=None,
email=None, phone=None, admin=False, staff=False, active=True):
if not username:
raise ValueError('아이디는 필수 항목입니다. (Account is required field.)')
if not password:
raise ValueError('비밀번호는 필수 항목입니다. (Password is required field.)')
if not full_name:
raise ValueError('사용자 이름은 필수 항목입니다. (Name is required field.)')
if not email:
raise ValueError('이메일은 필수 항목입니다. (E-mail is required field.)')
user_obj = self.model(
username=username,
full_name=full_name,
organization=organization,
phone=phone,
)
# Filled area from user
# user_obj.full_name = full_name
# user_obj.organization = organization
# user_obj.phone = phone
user_obj.username = username
user_obj.email = self.normalize_email(email)
user_obj.set_password(password)
# Invisible fields
user_obj.is_superuser = admin
user_obj.is_staff = staff
user_obj.is_active = active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self, username, password=None, full_name=None, organization=None, email=None, phone=None):
user = self.create_user(
username=username,
password=password,
full_name=full_name,
email=email,
organization=organization,
phone=phone,
staff=True,
)
user.save(using=self._db)
return user
def create_superuser(self, username, password=None, full_name=None, organization=None, email=None, phone=None):
user = self.create_user(
username=username,
password=password,
full_name=full_name,
email=email,
organization=organization,
phone=phone,
staff=True,
admin=True,
)
user.save(using=self._db)
return user
And my form python file.
./Users/form.py
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'full_name', 'email', 'organization', 'phone',)
def clean_email(self):
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_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
class UserAdminCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'full_name', 'email', 'organization', 'phone',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
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 = ('username', 'password', 'email', 'organization', 'phone', 'is_active', 'is_superuser',)
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"]
Honestly I have no idea what will show you up to..
Maybe I have to show you my admin.py too? anyways,
Here is my vue.js SignUp axios.
data: () => ({
username: '',
password: '',
re_pass: '',
full_name: '',
email: '',
organization: '',
phone: ''
}),
sign_up () {
this.$validator.validateAll()
if (this.password !== this.re_pass) {
alert('check the password')
document.getElementById('re_password').focus()
} else {
let axios = this.$axios
let formData = new FormData()
formData.append('username', this.username)
formData.append('password', this.password)
formData.append('full_name', this.full_name)
formData.append('email', this.email)
formData.append('organization', this.organization)
formData.append('phone', this.phone)
const baseURI = 'http://127.0.0.1:8000' //my localhost api
const config = {
headers: {
'Content-Type': 'application/json'
}
}
/* Do axios post */
axios.post(`${baseURI}/users/`, formData, config)
.then((response) => {
alert('회원가입 되었습니다. (You Signed Up.)')
this.$router.push({
name: 'sign_in'
})
})
.catch((e) => {
console.error(e)
alert('전송 중 문제가 발생하였습니다. 다시시도 해주세요. (The error accurred. Please try to do again.)')
})
}
}
Actually it works but I hope it would be worked more naturally with
automatic hashed password with default set up as Django model.
Sorry about that complicated question.
Honestly I posted first time in this site and I'm not English speaker too.
I really struggled to find some example Django with Vue.js, and custom user model so..
Thanks to read that all and Don't hesitate to tell me.
Have a good day!
++ Add my serializers.py too
./Users/serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
# Model set
model = User
# Field set
fields = ('id', 'username', 'email', 'organization', 'full_name', 'phone', 'password',
'is_superuser', 'is_active', 'is_staff', 'last_login', 'created_date', 'updated_date')
And my views.
./Users/views.py
from rest_framework import viewsets
from .serializers import UserSerializer
from .models import User
class UsersViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
Project url.
./Project_name/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token
from rest_framework import routers
from Users.views import UsersViewSet
router = routers.DefaultRouter()
router.register('users', UsersViewSet)
urlpatterns = [
# Normal urls
path('admin/', admin.site.urls),
path('', include(router.urls)),
# JWT auth
path('api-token-auth/', obtain_jwt_token),
path('api-token-refresh/', refresh_jwt_token),
]
Thanks again.
#dethos He gave me a clue for this.
So finally I found a solution here
Why isn't my Django User Model's Password Hashed?
And I will share my edited serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
# Model set
model = User
# Field set
fields = ('id', 'username', 'email', 'organization', 'full_name', 'phone', 'password',
'is_superuser', 'is_active', 'is_staff', 'last_login', 'created_date', 'updated_date')
def create(self, validated_data):
password = validated_data.pop('password', None)
is_active = validated_data.pop('is_active', True)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
def update(self, instance, validated_data):
for attr, value in validated_data.items():
if attr == 'password':
instance.set_password(value)
else:
setattr(instance, attr, value)
instance.save()
return instance
I added 'set_password', and 'is_active''s default value.

django.core.exceptions.FieldError: Unknown field(s) specified by user

I'm using Django 2.0
I have extended AbstractBaseUser model to create a custom User model.
In my accounts/models.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None, is_staff=False, is_admin=False, is_active=False):
if not email:
raise ValueError('User must have an email address')
if not password:
raise ValueError('User must have a password')
user = self.model(
email=self.normalize_email(email)
)
user.is_staff = is_staff
user.is_admin = is_admin
user.is_active = is_active
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, password=None):
return self.create_user(
email,
password=password,
is_staff=True,
is_active=True
)
def create_superuser(self, email, password=None):
return self.create_user(
email,
password=password,
is_staff=True,
is_admin=True,
is_active=True
)
class User(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(max_length=250, blank=False, unique=True)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
groups = models.ManyToManyField(Group, blank=True)
last_login = models.DateTimeField(auto_now=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
objects = UserManager()
#property
def is_staff(self):
return self.is_staff
#property
def is_active(self):
return self.is_active
#property
def is_superuser(self):
return self.is_admin
def __str__(self):
if self.first_name is not None:
return self.get_full_name()
return self.email
def get_full_name(self):
if self.last_name is not None:
return self.first_name + ' ' + self.last_name
return self.get_short_name()
def get_short_name(self):
return self.first_name
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
and to use this User model for admin as well. I have added below code to
accounts/admin.py as given in example
from accounts.models import User
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.contrib.auth.models import Group
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(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', 'first_name', 'last_name', 'is_active', 'is_admin', 'is_staff')
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"]
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# 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', 'first_name', 'last_name', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name',)}),
('Permissions', {'fields': ('is_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', 'first_name', 'last_name', 'password1', 'password2')}
),
)
search_fields = ('email', 'first_name', 'last_name',)
ordering = ('email', 'first_name', 'last_name',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
But when I run
python manage.py makemigrations
It gives error as
File "/Users/anuj/code/PyCharm/notepad/src/accounts/admin.py", line 37, in <module>
class UserChangeForm(forms.ModelForm):
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (is_staff, is_active) specified for User
removing is_staff and is_active from UserChangeForm works fine. I have even fields added to model.
Since you are using a custom user model for authentication you must say so in your settings
In settings.py write:
AUTH_USER_MODEL = 'accounts.User'
Source