I created an user app MyUser which is an extension of AbstractBaseUser. I was under the impression that the model MyUser will replace the standard Auth.User, as long as it is mentioned in settings.py
AUTH_PROFILE_MODULE = 'profile.MyUser'
My trouble is now that I can't set the permissions for users registered in the MyUser model. When I try to set the group memberships and permissions, I get the error User' instance expected, got <MyUser: username>.
How can I add users of my user model to the permissions and correct groups?
class MyUserManager(BaseUserManager):
def create_user(self, username, email, phone, password=None, company=False):
if not email:
raise ValueError('Users must have an email address')
if not username: username = email.split('#')[0]
user = self.model(
email=MyUserManager.normalize_email(email),
username=username,phone=phone,)
user.set_password(password)
user.save(using=self._db)
# add to user group and set permissions
if company:
g = Group.objects.get(name='company')
p = Permission.objects.get(codename='add_company')
else:
g = Group.objects.get(name='user')
p = Permission.objects.get(codename='add_user')
g.user_set.add(user)
user.user_permissions.add(p)
return user
class MyUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True, blank=True, null=True)
email = models.EmailField(max_length=254, unique=True, db_index=True)
phone = models.CharField(_('Phone Number'), max_length=25, blank=True, null=True,)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['phone']
objects = MyUserManager()
def get_full_name(self):
return self.email
...
Just add PermissionsMixin to your model declaration! :)
class MyUser(AbstractBaseUser, PermissionsMixin):
...
Here is the relevant part of Django docs.
You've probably resolved your issue but for completeness did you mean to refer to setting AUTH_USER_MODEL vs AUTH_PROFILE_MODULE when creating a custom user model in Django 1.5.
ref: https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#substituting-a-custom-user-model
Related
I want to use an extra field let me distinguish between user roles.
For that, I've overriden the User class:
class User(AbstractUser):
role = models.CharField(max_length=21, blank=False)
I've also put this in settings.py:
AUTH_USER_MODEL = 'shopping.User'
The problem is that I have the new field in my database, but, if I want to create a new user using the admin, it doesn't ask me for the role.
I suppose that I have to override the save method too, but I don't know how.
Thanks in advance
I would recommend you to rewrite used Model-Like this and it will much easier and you can add filed like you want
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
#You can set here required field for register new user.
class UserManager(BaseUserManager):
def create_user(self, email, username, password=None, **extra_fields):
if not email:
raise ValueError("Users must have an email address")
if not username:
raise ValueError("Users must have a username")
user = self.model(
email=self.normalize_email(email), username=username.lower(), **extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(email, username, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(max_length=255, unique=True)
fullname = models.CharField(max_length=60, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
role = models.CharField(max_length=21, blank=False)
objects = UserManager()
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"] #Requiref field set here
AUTH_USER_MODEL = "shopping.User"
I'm creating web based system, where I have 5 or 6 different roles and access type. I made a research how to achieve this and everything is made only when create group in django admin and assign user into it but only from the administrative part. I need to create this from the views. I already have a form to add users with email and drop down menu to set the role type.
Any suggestions will be appreciated, because till now I don't have idea how to achieve this without to assign the users from django admin.
my model.py for users:
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
ADMIN = 1
RECEPTION = 2
HEADOFDEPARTMENT = 3
EMPLOYEE = 4
PATIENT = 5
NOTACTIVE = 6
ROLE_CHOICES = (
(ADMIN, 'Admin'),
(RECEPTION, 'Reception'),
(HEADOFDEPARTMENT, 'HeadOfDepartment'),
(EMPLOYEE, 'Employee'),
(PATIENT, 'Patient'),
(NOTACTIVE, 'NotActive'),
)
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, blank=True, default=True, null=True)
#email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, blank=True, default='')
is_superuser = models.BooleanField(default=True)
is_admin = models.BooleanField(default=True)
is_employee = models.BooleanField(default=True)
is_headofdepartment = models.BooleanField(default=True)
is_reception = models.BooleanField(default=True)
is_patient = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
like this
from django.contrib.auth.models import Group
def ViewFunc(request):
... #your func
role = Group.objects.get(name='role')
role.user_set.add(user)
You retrieve the user object in the way you want in views, you add it in the user set in the group, done.
EDIT
Adding user Foo to Admins Group.
from django.contrib.auth.models import Group, User
def ViewFunc(request):
user = User.objects.get(username = 'Foo')
role = Group.objects.get(name='Admins')
role.user_set.add(user)
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 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.
How to make my CustomUser appear in admin under auth app like built-in user? I know there was a question like that here and I followed the solution people suggested, but what their solution do, is that it makes a Customer User in my app, not in an auth app, so like any other model that I create.
Here are my models:
class CustomUserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None,
**extra_fields):
'''
Create a CustomUser with email, name, password and other extra fields
'''
now = timezone.now()
if not email:
raise ValueError('The email is required to create this user')
email = CustomUserManager.normalize_email(email)
cuser = self.model(email=email, first_name=first_name,
last_name=last_name, is_staff=False,
is_active=True, is_superuser=False,
date_joined=now, last_login=now,)
cuser.set_password(password)
cuser.save(using=self._db)
return cuser
def create_superuser(self, email, first_name, last_name, password=None,
**extra_fields):
u = self.create_user(email, first_name, last_name, password,
**extra_fields)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
class CustomUser(AbstractBaseUser, PermissionsMixin):
'''
Class implementing a custom user model. Includes basic django admin
permissions and can be used as a skeleton for other models.
Email is the unique identifier. Email, password and name are required
'''
email = models.EmailField(_('email'), max_length=254, unique=True,
validators=[validators.validate_email])
username = models.CharField(_('username'), max_length=30, blank=True)
first_name = models.CharField(_('first name'), max_length=45)
last_name = models.CharField(_('last name'), max_length=45)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Determines if user can access the admin site'))
is_active = models.BooleanField(_('active'), default=True)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
def get_full_name(self):
'''
Returns the user's full name. This is the first name + last name
'''
full_name = "%s %s" % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns a short name for the user. This will just be the first name
'''
return self.first_name.strip()
And I also want to add ManyToManyField to 2 other models I have and make them appear in the user form in admin.
Does it mean that I have to write my own form? Or maybe I can just copy the source code for the built-in user form and change it to my names?
Thanks a lot in advance!
Why do you need it in the auth app? Why does that matter? If you really need to do that, you can just add an app_label variable in the `Meta
class Meta:
app_label = 'auth'
This will change the table names, so you will need to migrate those.
for the ManyToManyField, I would just override the appropriate auth forms and add those fields.