When user is registered with a form or in admin the password is not hashed, as with the superuser.
Any help appreciated. I cannot seem to figure this out. Oh, I am not able to login either. Exept from superuser.
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'theapp',
'rest_framework',
'userapp',
]
.
.
.
AUTH_USER_MODEL = "userapp.UserAccount"
model.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserAccountManager(BaseUserManager):
def create_user(self, email, password=None):
if not email or len(email) <= 0:
raise ValueError("Email field is required !")
if not password:
raise ValueError("Password is must !")
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(
email=self.normalize_email(email),
password=password
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserAccount(AbstractBaseUser):
class Types(models.TextChoices):
STUDENT = "STUDENT", "student"
TEACHER = "TEACHER", "teacher"
type = models.CharField(
max_length=8, choices=Types.choices, default=Types.TEACHER)
email = models.EmailField(max_length=200, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
phone_no = models.CharField(max_length=10)
# special permission which define that
# the new user is teacher or student
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
USERNAME_FIELD = "email"
# defining the manager for the UserAccount model
objects = UserAccountManager()
def __str__(self):
return str(self.email)
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
def save(self, *args, **kwargs):
if not self.type or self.type == None:
self.type = UserAccount.Types.TEACHER
return super().save(*args, **kwargs)
class StudentManager(models.Manager):
def create_user(self, email, password=None):
if not email or len(email) <= 0:
raise ValueError("Email field is required !")
if not password:
raise ValueError("Password is must !")
email = email.lower()
user = self.model(
email=email
)
user.set_password(password)
user.save(using=self._db)
return user
def get_queryset(self, *args, **kwargs):
queryset = super().get_queryset(*args, **kwargs)
queryset = queryset.filter(type=UserAccount.Types.STUDENT)
return queryset
class Student(UserAccount):
class Meta:
proxy = True
objects = StudentManager()
def save(self, *args, **kwargs):
self.type = UserAccount.Types.STUDENT
self.is_student = True
return super().save(*args, **kwargs)
class TeacherManager(models.Manager):
def create_user(self, email, password=None):
if not email or len(email) <= 0:
raise ValueError("Email field is required !")
if not password:
raise ValueError("Password is must !")
email = email.lower()
user = self.model(
email=email
)
user.set_password(password)
user.save(using=self._db)
return user
def get_queryset(self, *args, **kwargs):
queryset = super().get_queryset(*args, **kwargs)
queryset = queryset.filter(type=UserAccount.Types.TEACHER)
return queryset
class Teacher(UserAccount):
class Meta:
proxy = True
objects = TeacherManager()
def save(self, *args, **kwargs):
self.type = UserAccount.Types.TEACHER
self.is_teacher = True
return super().save(*args, **kwargs)
views.py
from django.shortcuts import render, redirect
from userapp.forms import StudentRegistrationForm, TeacherRegistrationForm
def register_student(request):
if request.method == 'POST':
form = StudentRegistrationForm(request.POST)
if form.is_valid():
form.save()
# Redirect to a success page or login page
return redirect('login-user')
else:
form = StudentRegistrationForm()
return render(request, 'userapp/student_register.html', {'form': form})
def register_teacher(request):
if request.method == 'POST':
form = TeacherRegistrationForm(request.POST)
if form.is_valid():
form.save()
# Redirect to a success page or login page
return redirect('login-user')
else:
form = TeacherRegistrationForm()
return render(request, 'userapp/teacher_register.html', {'form': form})
forms.py
from django import forms
from .models import UserAccount, Student, Teacher
class StudentRegistrationForm(forms.ModelForm):
class Meta:
model = Student
fields = ['email', 'password']
class TeacherRegistrationForm(forms.ModelForm):
class Meta:
model = Teacher
fields = ['email', 'password']
urls.py
from django.urls import path, include
from userapp import views
from django.contrib.auth.views import LoginView
urlpatterns = [
path('login/', LoginView.as_view(template_name="userapp/loginpage.html"),
name="login-user"),
path('register/student/', views.register_student, name='register_student'),
path('register/teacher/', views.register_teacher, name='register_teacher'),
]
student_register.html
<!DOCTYPE html>
<html>
<body>
<h2>Student Registration</h2>
<form method="post" action="{% url 'register_student' %}">
{% csrf_token %}
<!-- {{ form.as_p }} -->
<div class="container">
<h1>Register Student</h1>
<p>Please fill in this form to create an account.</p>
<hr>
<label for="email"><b>Email</b></label>
<input type="text" placeholder="Enter Email" name="email" id="email" required>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="password" id="password" required>
<hr>
<button type="submit" class="registerbtn">Register</button>
</div>
</div>
<!-- <button type="submit">Register</button> -->
</form>
</body>
</html>
Been searching for an answer ....
Tried to change in models (see below) without any effect and without really understanding....
user.set_password(password)
...
user.set_password(self.cleaned_data["password"])
Thanks a lot.
Your form is calling the model's .save() and not the manager's .create_user(). The Form instance is an model instantiated from the form's fields, but it hasn't been through the create_user() process.
Because the registration form will (presumably) only ever be creating a user, you could try something like the below :
if form.is_valid():
Student.objects.create_user(form.cleaned_data["email"],password=form.cleaned_data["password"])