Django CustomUserModel email field case sensitive - python

Email field in the Django(3.0) Custom User Model is case sensitive, I tried various ways to make it case-insensitive but no success so far.
Code
forms.py
class UserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('first_name','last_name','username','email','password1','password2')
class UserChangeForm(UserChangeForm):
class Meta:
model = User
fields = ('first_name','last_name','username','email',)
class UserUpdateForm(forms.ModelForm):
'''
model form are the form that work with specific user model
'''
class Meta:
model = User
fields = ('first_name','last_name','username','email',)
class ProfileUpdateForm(forms.ModelForm):
'''
model form are the form that work with specific user model
'''
class Meta:
model = Profile
fields = ['image']
manager.py
class UserManager(BaseUserManager):
def create_user(self, email, username, first_name, last_name, password=None):
if not email:
raise ValueError('Must have Email')
if not username:
raise ValueError('Must have username')
if not first_name:
raise ValueError('Must have first_name')
if not last_name:
raise ValueError('Must have last name')
user = self.model(
email=self.normalize_email(email),
username=username,
first_name=first_name,
last_name=last_name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, first_name, last_name, password=None):
user = self.create_user(
email=email,
username=username,
first_name=first_name,
last_name=last_name,
password=password,
)
user.is_active = True
user.is_staff = True
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
Model.py
class User(AbstractBaseUser):
# compulsory fields
email = models.EmailField(max_length=255, unique=True)
username = models.CharField(
unique=True, max_length=255, null=True, blank=False)
first_name = models.CharField(
unique=False, max_length=255, null=True, blank=False, verbose_name='First Name')
last_name = models.CharField(
unique=False, max_length=255, null=True, blank=False, verbose_name='Last Name')
date_joined = models.DateTimeField(default=timezone.now)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'username']
objects = UserManager()
def __str__(self):
return f'{self. username}'
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return self.is_admin
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
there are two models that interact with User, one is User and other is Profile. (Profle handles images)
Things already tried
One of the very obvious things to try is to make email lowercase in manager.py before any authentication and so I did like this
manage.py (modified)
user = self.model(
email=self.normalize_email( **email.lower()** ), # <- notice change here
username=username,
first_name=first_name,
last_name=last_name,
)
user = self.create_user(
email=email.lower() , # <-- notice change here
username=username,
first_name=first_name,
last_name=last_name,
password=password,
)
but this didn't work.
Second was this post, this is another StackOverflow post which I followed which didn't work either
I am trying to solve this problem for hours and can't think of anything else, would really appreciate some advice.

Related

Django: Custom User Model with Autoincrementing Id

I am trying to use Django Authentication and I want to create a custom model for the user that has an autoincrementing integer as id. I know about uuid library, but I want the id to be an integer number, that is why I want to avoid it.
My code looks like:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyAccountManager(BaseUserManager):
def create_user(self, first_name, last_name, email, username, avatar, password=None):
if not username:
raise ValueError('User must have an username')
if not avatar:
raise ValueError('User must have an avatar')
user = self.model(
email=self.normalize_email(email),
username=username,
avatar=avatar,
first_name=first_name,
last_name=last_name
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, first_name, last_name, email, username, avatar, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
avatar=avatar,
password=password,
first_name=first_name,
last_name=last_name
)
user.is_admin = True
user.is_active = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
username = models.CharField(max_length=50, unique=True)
email = models.CharField(max_length=50, unique=True)
avatar = models.CharField(max_length=200)
# required
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superadmin = models.BooleanField(default=False)
USERNAME_FIELD = 'id'
REQUIRED_FIELDS = ['username', 'first_name', 'last_name', 'email', 'avatar']
objects = MyAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, add_label):
return True
The problem is that I still want to log in with the username, not the id. Also, as it autoincrements, it would be nice that I won't have to manually introduce it when I create a superuser from the console.
Is this possible?
I tried to solve your requirement... using save method overriding
Model code:
class CustomUserModel(AbstractBaseUser, PermissionsMixin):
auto_id = models.PositiveBigIntegerField(unique=True)
username = models.CharField(max_length=255, unique=True)
email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
mobile_no = models.PositiveIntegerField(verbose_name="mobile number",unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
objects = CustomUserManager()
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['email','mobile_no']
def save(self, *args, **kwargs):
count_id = CustomUserModel.objects.all().count()
self.auto_id = count_id+1
super(CustomUserModel, self).save(*args, **kwargs)
def __str__(self):
return self.email
Output admin panel view:

Serializers VS ModelForms in User Registration, Django Rest Framework

What to use while registering a user ? Serializer or ModelForms ?
I have been using DRF since a long time now but I have been opting for old school ModelForm (forms.ModelForm) method for user registration. I just want to know that is it necessary to use modelForm for user Registration or we could use serializer as well like we do for all the APIs ?
PS : I have overriden the user Modal along with the Managers :
class MyAccountManager(BaseUserManager):
def create_user(self, email, name, password):
if not email:
raise ValueError('User must have an email address')
if not name:
raise ValueError('User must have a name')
user = self.model(
email=self.normalize_email(email),
name=name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
user = self.create_user(
name=name,
email=self.normalize_email(email),
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.is_customer = False
user.save(using=self._db)
return user
`
class User(AbstractBaseUser, CreationUpdationMixin):
first_name = None
last_name = None
date_joined = None
email = models.EmailField(unique=True)
name = models.CharField(max_length=200)
phone = models.CharField(max_length=20, default='')
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_customer = models.BooleanField(default=True)
is_seller = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
objects = MyAccountManager()
`

Django saving the registration extends AbstractBaseUser

Good day SO.
I am new to Django and having troubles with something basic. What I am trying to do is when I click on register, I want to create an Account and at the same time, a company account.
When I click on sumbit, the template returns my Account(the OneToOneField) This field is required.
Though my methods might be not aligned with good practice, but I hope that you can help me with this. I have been trying to check with other resources for two days but I can't seem to find the solution to my concern.
Here is my forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import Account, CompanyAccount
class AccountCreationForm(UserCreationForm):
email = forms.EmailField(max_length=60, help_text="Required")
class Meta:
model = Account
fields = ("email", "username", "password1", "password2", "account_type")
class CompanyAccountForm(forms.ModelForm):
class Meta:
model = CompanyAccount
fields = "__all__"
my models.py:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
# Create your models here.
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, account_type, password):
if not email:
raise ValueError("Users must have an Email Address")
if not username:
raise ValueError("Users must have an Username")
if not account_type:
raise ValueError("Users must have an Account Type")
user = self.model(
email=self.normalize_email(email),
username=username,
password=password,
account_type=account_type,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, account_type, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
account_type=account_type,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='Email', max_length=60, default='', null=False, unique=True)
username = models.CharField(verbose_name='Username', max_length=50, default='', null=False, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_joined = models.DateTimeField(verbose_name='last joined', 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)
ACCOUNT_TYPE_CHOICES = (
(1, 'Applicant'),
(2, 'Company'),
(3, 'Client'),
)
account_type = models.PositiveSmallIntegerField(default=0, choices=ACCOUNT_TYPE_CHOICES)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'account_type', ]
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
class CompanyAccount(models.Model):
account = models.OneToOneField(Account, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
company_name = models.CharField(max_length=100, default='', null=False)
views.py
context = {}
if request.method == "POST":
rForm = AccountCreationForm(request.POST)
cForm = CompanyAccountForm(request.POST)
if rForm.is_valid() and cForm.is_valid():
rForm.save()
cForm.save()
else:
rForm = AccountCreationForm()
context['rForm'] = rForm
cForm = CompanyAccountForm()
context['cForm'] = cForm
return render(request, 'registration/company_registration_form.html', context)
If you want your model's field to be allowed to be empty when submitting forms, add blank=True:
account = models.OneToOneField(Account, on_delete=models.CASCADE, blank=True)
https://docs.djangoproject.com/en/3.1/ref/models/fields/

Group object has no attribute user_set

I'm using a custom User created with AbstractBaseUser and I tried to add users to a specific group using the django admin. But there were no option to add users to a group. So I found a solution from the stack overflow and It gave me the capability to add users to the group I created. But after saving the user It gives me an error saying Group object has no attribute user_set
My User Model
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Users must have an email address")
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),
username=username,
password=password,
)
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=80, unique=True)
username = models.CharField(max_length=30, unique=True)
first_name = models.CharField(max_length=100,null=True)
last_name = models.CharField(max_length=100,null=True)
phone_no = models.CharField(max_length=12,null=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)
is_teacher = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
Code I got from the stackoverflow
User = get_user_model()
# Create ModelForm based on the Group model.
class GroupAdminForm(forms.ModelForm):
class Meta:
model = Group
exclude = []
# Add the users field.
users = forms.ModelMultipleChoiceField(
queryset=User.objects.all(),
required=False,
# Use the pretty 'filter_horizontal widget'.
widget=FilteredSelectMultiple('users', False)
)
def __init__(self, *args, **kwargs):
# Do the normal form initialisation.
super(GroupAdminForm, self).__init__(*args, **kwargs)
# If it is an existing group (saved objects have a pk).
if self.instance.pk:
# Populate the users field with the current Group users.
self.fields['users'].initial = self.instance.user_set.all()
def save_m2m(self):
# Add the users to the Group.
self.instance.user_set.set(self.cleaned_data['users'])
def save(self, *args, **kwargs):
# Default save
instance = super(GroupAdminForm, self).save()
# Save many-to-many data
self.save_m2m()
return instance
Why this is giving me the error and is there any solutions for this
Thank You!
Django implements group relation in PermissionsMixin so you don't have that particular relation
You can implement AbstractUser class instead or add the Mixin
class User(AbstractBaseUser, PermissionsMixin):

How to fix "invalid password format or unknown hashing algorithm" error in Django?

Have a good day!
I created a custom user model in Django. When I try to create a admin user pofile - all is ok. But when I try to create a simple user profile, I see "invalid password format or unknown hashing algorithm" error in the admin interface. How to fix it?
class UserProfileManager(BaseUserManager):
def create_user(self, email, date_of_birth, password):
"""
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')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(email,
password=password,
date_of_birth=date_of_birth
)
user.is_admin = True
user.save(using=self._db)
return user
class UserProfile(AbstractBaseUser):
"""
The user-profile model
"""
MALE = 'MALE'
FEMALE = 'FEMALE'
GENDER = (
(MALE, 'Male'),
(FEMALE, 'Female'),
)
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
# The additional attributes we wish to include.
# The user's last name
last_name = models.CharField(max_length=50, blank=True)
# The user's first name
first_name = models.CharField(max_length=50, blank=True)
# The user's middle name
middle_name = models.CharField(max_length=50, blank=True)
# The user's birthday
date_of_birth = models.DateField()
# Gender
gender = models.CharField(max_length=6, choices=GENDER, default=MALE)
# The user's profile image
picture = models.ImageField(upload_to='profile_images', blank=True)
# Country
country = models.CharField(max_length=100, blank=True)
# City
city = models.CharField(max_length=100, blank=True)
# The user's full address
address = models.CharField(max_length=500, blank=True)
# The institution where the user works or studies
institution = models.CharField(max_length=500, blank=True)
# The user's job
job = models.CharField(max_length=500, blank=True)
# The user's registration date
registration_date = models.DateTimeField(default=datetime.datetime.now())
# How many tests complete this user and how many tests created this user.
rating = models.IntegerField(default=0)
objects = UserProfileManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
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?"
# Simplest possible answer: All admins are staff
return self.is_admin
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = UserProfile
fields = ('email', 'date_of_birth')
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(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = UserProfile
fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')
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"]
When I tried to create new user, I used get_or_created method. But I forgot to override it.
Now it works!))
try this
from django.contrib.auth.hashers import make_password
...
def create_user(self, email, date_of_birth, password):
"""
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')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(make_password(password))
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(email,
password=make_password(password),
date_of_birth=date_of_birth
)
user.is_admin = True
user.save(using=self._db)
return user
...

Categories

Resources