I just started a new Django project and I wanted to create my own customer user model instead of using the default. I pretty much followed the one in the documentation for 2.1 (my version of Django) except I added more fields and date_of_birth is called 'dob' and isn't required. But then when I create the superuser account, I can't log into the admin panel. It says, "Please enter the correct email address and password for a staff account. Note that both fields may be case-sensitive."
Here is my code:
users/models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.utils.translation import gettext_lazy as _
# Create your models here.
class UserManager(BaseUserManager):
# python manage.py createuser
def create_user(self, email: str, password: str=None) -> 'User':
if not email:
raise ValueError('Users must have a valid email address.')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
# python manage.py createsuperuser
def create_superuser(self, email, password) -> 'User':
user = self.create_user(
email=email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
_('email address'), help_text=_('An email address'), max_length=127, unique=True, null=False, blank=False
)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
first_name = models.CharField(_('first name'), help_text=_('The user\'s given name'), blank=False, max_length=32)
last_name = models.CharField(
_('last name'), help_text=_('The user\'s surname or family name'), blank=False, max_length=32
)
dob = models.DateField(_('date of birth'), help_text=_('User\'s date of birth'), blank=False, null=True)
hometown = models.CharField(_('hometown'), help_text=_('Hometown'), blank=True, max_length=64)
country = models.CharField(_('country'), help_text=_('Country'), blank=True, max_length=64)
objects = UserManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.first_name
def has_perm(self, perm, obj=None):
return self.is_staff
def has_module_perms(self, app_label):
return self.is_staff
#property
def is_staff(self) -> bool:
"""
Is the user a member of staff?
:return: If the user is an admin, then True. Else False
"""
return self.is_admin
I also changed my settings.py file to read:
AUTH_USER_MODEL = 'users.User'
and I made sure the app ('myproject.users.apps.UsersConfig') is added to the INSTALLED_APPS list. Note: my apps are all located one folder in, unlike the tutorial default. Ie:
myproject/
|-----> users/
|----->models.py
I think you missed one thing in User model,
Change is_active = models.BooleanField(default=False) to is_active = models.BooleanField(default=True)
Hence your model be like,
class User(AbstractBaseUser):
is_active = models.BooleanField(default=True)
# other fields
From the official doc,
is_active
Boolean. Designates whether this user account should be considered
active. We recommend that you set this flag to False instead of
deleting accounts; that way, if your applications have any foreign
keys to users, the foreign keys won’t break.
Related
I have created Custom User Model in Django as follows, When I go to Admin and click on User and then it is keep showing me this error :
relation "users_user_groups" does not exist LINE 1: ... "auth_group"."name" FROM "auth_group" INNER JOIN "users_use...
models.py
from django.db import models
#from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
import uuid
class UserManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Email Requierd!")
if not username:
raise ValueError("Username required!")
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, PermissionsMixin):
userid = models.UUIDField(
default=uuid.uuid4, editable=False, primary_key=True)
username = models.CharField(max_length=255, unique=True)
email = models.EmailField(max_length=255, unique=True)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(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 = UserManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perm(self, app_label):
return True
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=85)
last_name = models.CharField(max_length=85)
recovery_email = models.EmailField(blank=True)
img = models.ImageField(default='aavtar.png', upload_to='media')
def __str__(self):
return self.user.username
Thanks for solving it in advance!
I was missing python manage.py makemigrations and python manage.py migrate but I didn't understand How tables user_permissions and user_groups are added in my PostgreSQL Server!
I always get the message "Please enter the correct email and password for a staff account. Note that both fields may be case-sensitive." I write in settings.py AUTH_USER_MODEL = 'eCommerce.User'.
And after I run makemigrations and migrate command I use these commands: python manage.py createsuperuser and then python manage.py runserver.
There is no errors in cmd but in the Django administration the above message shows.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self,email,name,password=None):
if not email:
raise ValueError("Users must enter an email address.")
if not name:
raise ValueError("Users must enter a name.")
user = self.model(
email= self.normalize_email(email),
name= name,
#phone_number = phone_number,
)
user.set_password=password
user.save(using=self._db)
return user
def create_superuser(self,email,name,password=None):
user = self.create_user(
name= name,
email= self.normalize_email(email),
password= password
)
user.is_admin = True
user.is_active = True
user.is_staff = True
user.is_superuser = True
user.save(using= self._db)
return user
class Address(models.Model):
street = models.CharField(max_length=50)
city = models.CharField(max_length=20)
postal_code = models.CharField(max_length=10)
class User(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=50, unique=True)
name = models.CharField(max_length=30)
phone_number = models.CharField(max_length=20)
billing_address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True
,related_name='billing_address')
shipping_address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True,
related_name='shipping_address')
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
#is_superuser = models.BooleanField(default=False)
#is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
objects = UserManager()
def __str__(self):
return "Email: " + str(self.email) + "Name: " + str(self.name)
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
add this under your user model
#property
def is_staff(self):
"Is the user a member of staff?"
return self.is_staff
or simply write it as
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
I have a User model using AbstractBaseUser. I have a model Employee using Model class. I want that when a user is created though sign up, the user inherits all the fields of Employee model. I have made a OnetoOne relation between User model and Employee. But after creating an user when I query employee model, I can not find any data related to the created User.
User manager:
class UserManager(BaseUserManager):
"""
Creates and saves a User with the given email and password.
"""
def create_user(self, email, username, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
username=username
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email,username, password):
user = self.create_user(
email,
password=password,
username=username
)
user.is_staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email,
password=password,
username=username
)
user.is_staff = True
user.is_admin = True
user.save(using=self._db)
return user
User:
class User(AbstractBaseUser):
"""
Creates a customized database table for user
"""
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
username = models.CharField(max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
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
I have extended the user model with a OnetoOne relation using OneToOneField(User, on_delete=models.CASCADE, null=True)
Employee model:
class Employee(models.Model):
"""
Create employee attributes
"""
employee_user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
e_id = models.IntegerField(unique=True, null=False)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
address = models.CharField(max_length=256, blank=True)
phone_number = models.CharField(max_length=128, blank=True)
email = models.EmailField(max_length=128, unique=True)
def get_absolute_url(self):
return reverse("employee:employee-list")
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Employee.objects.create(employee_user=instance)
instance.Employee.save()
In this model there is also a field named email. I have to keep this field because I am using this model to create a form for Employee creation. But the problem is, User model's email field is conflicting with employee email field. I have to keep both the email fields.
Can I update the employee email field with user email field?? If yes, then what should be the query???
you have created a custom user model soo you need to import he Auth_User_model from you setting file and than use that not the django inbuilt auth User.
You can do this
from django.conf import settings
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
I created a custom user model using AbstractBaseUser class. Code for the same is here.
class UserModel(AbstractBaseUser):
user_type_choices = (
(constants.USER_TYPE_ADMIN, 'Admin'),
(constants.USER_TYPE_INSTITUTE, 'Institute'),
(constants.USER_TYPE_STUDENT, 'Student')
)
sys_id = models.AutoField(primary_key=True, blank=True)
name = models.CharField(max_length=127, null=False, blank=False)
email = models.EmailField(max_length=127, unique=True, null=False, blank=False)
mobile = models.CharField(max_length=10, unique=True, null=False, blank=False)
user_type = models.PositiveSmallIntegerField(choices=user_type_choices, null=False, blank=True, help_text="Admin(1)/Institute(2)/Student(3)")
access_valid_start = models.DateTimeField(null=True, blank=True)
access_valid_end = models.DateTimeField(null=True, blank=True)
created_when = models.DateTimeField(null=True, blank=True )
created_by = models.BigIntegerField(null=True, blank=True)
last_updated_when = models.DateTimeField(null=True, blank=True)
last_updated_by = models.BigIntegerField(null=True, blank=True)
notes = models.CharField(max_length=2048, null=True, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
objects = MyUserManager()
USERNAME_FIELD = "email"
# REQUIRED_FIELDS must contain all required fields on your User model,
# but should not contain the USERNAME_FIELD or password as these fields will always be prompted for.
REQUIRED_FIELDS = ['name', 'mobile', 'user_type']
class Meta:
app_label = "accounts"
db_table = "users"
def __str__(self):
return self.email
def get_full_name(self):
return self.name
def get_short_name(self):
return self.name
def is_access_valid(self):
if self.access_valid_end > utility.now():
return True
else:
return False
def save(self, *args, **kwargs):
if not self.sys_id:
self.created_when = utility.now()
self.last_updated_when = utility.now()
return super(UserModel, self).save(*args, **kwargs)
Code for its manager is as below.
class MyUserManager(BaseUserManager):
use_in_migrations = True
def create_user(self, email, name, mobile, user_type, password):
return create_superuser(self, email, name, mobile, user_type, password)
# python manage.py createsuperuser
def create_superuser(self, email, name, mobile, user_type, password):
user = self.model(
email = email,
name = name,
mobile = mobile,
user_type = user_type,
access_valid_start = utility.now(),
access_valid_end = utility.get_access_end_date(),
created_when = utility.now(),
created_by = constants.COMMAND_LINE_USER_ID,
last_updated_when = utility.now(),
last_updated_by = constants.COMMAND_LINE_USER_ID,
notes = 'This user is created from command line. createsuperuser utility.'
)
user.set_password(password)
user.save(using=self._db)
return user
I also created the Authentication Backend.
class MyAuthBackend(object):
def authenticate(self, email, password):
try:
user = UserModel.objects.get(email=email)
if user.check_password(password):
return user
else:
return None
except UserModel.DoesNotExist:
logging.getLogger("error_logger").error("user with login %s does not exists " % login)
return None
except Exception as e:
logging.getLogger("error_logger").error("user with login %s does not exists " % login)
return None
def get_user(self, user_id):
# user_id must be the primary key of table.
try:
user = UserModel.objects.get(sys_id=user_id)
if user.is_active:
return user
return None
except UserModel.DoesNotExist:
logging.getLogger("error_logger").error("user with %(user_id)d not found")
return None
I have included custom user model and backend, both in settings file.
AUTH_USER_MODEL = 'accounts.UserModel'
AUTHENTICATION_BACKENDS = ('accounts.backends.MyAuthBackend',)
I created a superuser from command line but when I tried to login from admin login url, following error was thrown.
Please enter the correct email and password for a staff account. Note that both fields may be case-sensitive.
As suggest in this SO answer, I used fallback authentication backend and then it started throwing this error : 'UserModel' object has no attribute 'has_module_perms'. Which means fallback backend worked here. But it required to add below functions in custom user model.
def has_perm(self, perm, obj=None):
return self.is_superuser
# this methods are require to login super user from admin panel
def has_module_perms(self, app_label):
return self.is_superuser
and added is_superuser field as well. Now it is working fine.
So I have below questions :
Why I am not able to authenticate user using custom backend when trying to login from admin panel?
why function has_perm, is_staff and is_superuser fields are mandatory for login from admin panel?
Why has_perm function , is_staff and is_superuser fields are not required when logging in from my own login form?
You did authenticate but you are not authorized. Django Admin is using is_staff flag to authorize you in as stated in documentation
They are part of Django simple permission system which is by default used by Django admin as stated in documentation
You are not using permissions system otherwise they would be required as they are part of permission system.
Probably a very basic question.
How can i use my own legacy db table for authenticating login of the users in Django?
All the methods i am finding seem really confusing.
I want to use Django's own authentication system with modification of 'Persons' database table instead of 'User'.
This is an example of implementing custom authentication:
person/models.py:
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class PersonManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
if not email:
raise ValueError('Users must have a valid email address.')
if not kwargs.get('username'):
raise ValueError('Users must have a valid username.')
person = self.model(
email=self.normalize_email(email), username=kwargs.get('username')
)
person.set_password(password)
person.save()
return person
def create_superuser(self, email, password, **kwargs):
person = self.create_user(email, password, **kwargs)
person.is_superuser = True
person.save()
return person
class Person(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
# You may need to add more fields
is_superuser = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = PersonManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.email
def get_full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
def get_short_name(self):
return self.first_name
You will need to add AUTH_USER_MODEL = 'person.Person' to your settings.py file (I suppose that your app name is person). Now, your authentification system will use Person model instead of the default User model.
For more details, check this tutorial Extending Django's built-in User model