I deleted username field because I wanted user to be able to login with their email address, so I have this in my models.py :
class CustomUser(AbstractUser):
USER_TYPE = ((1, 'HOD'), (2, 'Staff'), (3, 'Student'))
username = None
email = models.EmailField(unique=True)
user_type = models.CharField(default=1, choices=USER_TYPE, max_length=1)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Student(models.Model):
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
gender = models.CharField(max_length=1, choices=GENDER)
address = models.TextField()
profile_pic = models.ImageField(upload_to='media')
session_start_year = models.DateField(null=True)
session_end_year = models.DateField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
In my views.py, I tried :
user = CustomUser.objects.create_user(email=email, password=password, user_type=3, first_name=first_name, last_name=last_name)
But I got create_user() missing 1 required positional argument: 'username'
How can I fix this?
You need to write a manager for a custom user model [Django-doc] to reimplement the create_user method.
You can thus implement a CustomUserManager:
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import UserManager
class CustomUserManager(UserManager):
def _create_user(self, email, password, **extra_fields):
email = self.normalize_email(email)
user = CustomUser(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
assert extra_fields['is_staff']
assert extra_fields['is_superuser']
return self._create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
# …
objects = CustomUserManager()
and then you register this manager thus as the objects manager.
Related
Whenever I am running the server I am getting the error
django.core.exceptions.ValidationError: ['“1” is not a valid UUID.']
I have used UUID v4 to change the user id to a random id. But my code is not working.
I have deleted and re-migrated migrations many times. But no improvement at all?
how can I fix the probelm?
#models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,PermissionsMixin,BaseUserManager
import uuid
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, first_name, last_name, mobile, **extra_fields):
if not email:
raise ValueError("Email must be provided")
if not password:
raise ValueError('Password is not provided')
user = self.model(
email = self.normalize_email(email),
first_name = first_name,
last_name = last_name,
mobile = mobile,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password, first_name, last_name, mobile, **extra_fields):
extra_fields.setdefault('is_staff',True)
extra_fields.setdefault('is_active',True)
extra_fields.setdefault('is_superuser',False)
return self._create_user(email, password, first_name, last_name, mobile, password,
**extra_fields)
def create_superuser(self, email, password, first_name, last_name, mobile,
**extra_fields):
extra_fields.setdefault('is_staff',True)
extra_fields.setdefault('is_active',True)
extra_fields.setdefault('is_superuser',True)
return self._create_user(email, password, first_name, last_name, mobile,
**extra_fields)
# Create your User Model here.
class User(AbstractBaseUser,PermissionsMixin):
# Abstractbaseuser has password, last_login, is_active by default
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(db_index=True, unique=True, max_length=254)
first_name = models.CharField(max_length=240)
last_name = models.CharField(max_length=255)
mobile = models.CharField(max_length=50)
address = models.CharField( max_length=250)
is_staff = models.BooleanField(default=True) # must needed, otherwise you won't be able to
loginto django-admin.
is_active = models.BooleanField(default=True) # must needed, otherwise you won't be able
to loginto django-admin.
is_superuser = models.BooleanField(default=False) # this field we inherit from
PermissionsMixin.
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name','last_name','mobile']
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
#ERROR
I'm making a django website and I had made groups for the admin page access(Admin, Content Writer, Users). What I want is when a user signs up they should be assigned the specific group based on from which form they are signing in/up.
Here is my models.py file for accounts app
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
# Custom User Manager
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, first_name, last_name=None, **extra_fields):
if (not email):
raise ValueError("Email Must Be Provided")
if (not password):
raise ValueError("Password is not Provided")
user = self.model(
email=self.normalize_email(email),
first_name=first_name,
last_name=last_name,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password, first_name, last_name=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_active', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, first_name, last_name, **extra_fields)
def create_user_with_groups(self, email, password, first_name, last_name=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, first_name, last_name, **extra_fields)
def create_superuser(self, email, password, first_name, last_name=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('is_superuser', 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, first_name, last_name, **extra_fields)
# Custom user Model
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, unique=True, max_length=254)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255, null=True, blank=True)
mobile = models.CharField(max_length=50, null=True, blank=True)
address = models.CharField(max_length=250, null=True, blank=True)
# profile_pic = models.ImageField(null=True, blank=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name']
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
here is what my Groups look like in admin page
In my CustomUserManager class, can we add one more method, like create_content_writer, which has the functionality of create_user but it sets the is_staff to true and is_active to true and adds that user to Content Writer group when it is created.
Or if there is more efficient way of doing so, then please tell, because in future if the groups are gonna increase then I'll have to make separate function for each group. If all of this can be achieved from one single function, it would be really great!
I am trying to createsuper user
when I entered email and password I got this error
File "/mnt/c/Users/ZAKARIA/Desktop/project/env/lib/python3.8/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 232, in handle
self.UserModel._default_manager.db_manager(database).create_superuser(
TypeError: create_superuser() missing 2 required positional arguments: 'first_name' and 'last_name'
my class managers
from django.contrib.auth.base_user import BaseUserManager
class UserManger(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
if not email:
raise ValueError("Users must have an email address")
if not first_name or last_name:
raise ValueError("Users must have a first and last name")
user = self.model(
email=self.normalize_email(email),
first_name=first_name,
last_name=last_name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email,password, first_name, last_name):
user = self.create_user(
email=self.normalize_email(email),
password=password,
first_name=first_name,
last_name=last_name,
)
user.set_password(user.password)
#user.is_staff = True
user.is_superuser = True
#user.is_admin = True
user.save(using=self._db)
return user
models
import datetime
from django.core.mail import send_mail
from distutils.command.upload import upload
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils import timezone
from phonenumber_field.modelfields import PhoneNumberField
from .managers import UserManger
GENDER_MALE = "m"
GENDER_FEMALE = "f"
OTHER = "o"
GENDER_CHOICES = (
(GENDER_MALE, "Male"),
(GENDER_FEMALE, "Female"),
(OTHER, "Other"),
)
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
picture = models.ImageField(
upload_to='images/users', null=True, verbose_name="")
is_active = models.BooleanField(default=True)
#is_staff = models.BooleanField(default=False)
phone = PhoneNumberField()
is_admin = models.BooleanField(default=False)
#credits =models.PositiveIntegerField(default=100)
linkedin_token = models.TextField(blank=True, default='')
expiry_date = models.DateTimeField(null=True, blank=True)
objects = UserManger()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name' , 'last_name']
def get_full_name(self):
full_name = '%S %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def __str__(self):
return self.email
def has_perm(self, prem, obj=None):
"Does the user have a specific permission?"
return True
def has_module_perm(self, app_label):
"Does the user have permissions to view the app `app_label`?"
return True
''''
#property
def is_staff(self):
"Is the user a member of staff"
return self.is_admin'''
"""#property
def is_out_of_credits(self):
"Is the user out of credits"
return self.credits > 0
#property
def has_sufficient_credits(self,cost):
return self.credits - cost >= 0
"""
#property
def linkedin_signed_in(self):
return bool(self.linkedin_token) and self.expiry_date > timezone.now()
I have been seeing a lot of questions similar to this but i still don't understand the answers given, some say add positional arguements, I don't quite understand
can any one help me to solve this problem ?
That's probably because you have some extra fields in the UserModel that are not passing accurately in the create_superuser.
Try **extra_fields arg instead of passing first_name, last_name separately, as the docs about Manager methods suggest,
The extra_fields keyword arguments are passed through to the User’s
init method to allow setting arbitrary fields on a custom user model.
So, modify your UserManger class according to this and then this will rectify the problem.
Modified Code:
class UserManger(BaseUserManager):
"""Define a model manager for User model"""
def _create_user(self, email, password=None, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError('The given email must be set')
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password=None, **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)
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)
Now you can set first_name, last_name, as REQUIRED_FIELDS in the UserModel, like this.
REQUIRED_FIELDS = ['first_name' , 'last_name']
For detailed information on BaseUserManager, you can also check Docs
Edit:
After seeing your UserModel, this would be better the use AbstractUser instead of AbstractBaseUser, AbstractUser will carry all the fields that a default Django User has. So you don't have to define the fields like first_name, last_name, is_staff or etc...
That is how you can modify it
# import
from django.contrib.auth.models import AbstractUser
# Model
class User(AbstractUser):
username = None # as you are using email as username
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
picture = models.ImageField(
upload_to='images/users', null=True, verbose_name="")
phone = PhoneNumberField()
is_admin = models.BooleanField(default=False)
#credits =models.PositiveIntegerField(default=100)
linkedin_token = models.TextField(blank=True, default='')
expiry_date = models.DateTimeField(null=True, blank=True)
objects = UserManger()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name' , 'last_name']
# Do anything else here
missing 2 required positional arguments: 'request' and 'eml'
If you face this error and you use class based view so please remove your self and other parameter which is define in function. Your function need only request as parameter run properly. I am just sharing my experience because I have lost my lot of time behind this error.
def delete(self, request, eml):
print(request.GET.get('d_id'))
return HttpResponse('delete')
It's working fine for me.
def delete(request):
print(request.GET.get('d_id'))
return HttpResponse('delete')
If you use class based view even then remove self parameter from method. I hope it will help you.
I've been on dj_rest_auth on this project. Trying to add extra fields to the custom user model but it only saves the email and password. I think I have everything right but nothings working.
Heres my user model
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'
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
phone = models.CharField(max_length=30, blank=True)
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
serializers.py
class UserSerializer(serializers.ModelSerializer):
phone = serializers.CharField(max_length=30, allow_blank=True)
first_name = serializers.CharField(max_length=30, allow_blank=True)
last_name = serializers.CharField(max_length=30, allow_blank=True)
class Meta:
model = CustomUser
fields = ('id', 'email', 'first_name', 'last_name', 'phone')
def save(self, request):
user = super().save(request)
user.phone = self.data.get('phone')
user.first_name = self.data.get('first_name')
user.last_name = self.data.get('last_name')
user.save()
return user
settings.py
AUTH_USER_MODEL = 'users.CustomUser'
REST_AUTH_REGISTER_SERIALIZERS = {
'REGISTER_SERIALIZER': 'users.serializers.UserSerializer',
}
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
and finally in my urls.py
path('register/', RegisterView.as_view()),
From postman I send this post request
{
"email": "ahsan44411#gmail.com",
"password": "ahsan44411",
"password2": "ahsan44411",
"first_name": "ahsan",
"last_name": "mukhtar",
"phone": "64763868"
}
It only saves the email address, phone, first_name, last_name are not saved.
I have searched read nearly every problem on stackoverflow, without any luck, now I am posting here, please inform me if problem is not clear.
You can use the create function to save user data like this. Hope this answer will help you to solve your problem.
def create(self, data):
u = User(username=data["username"], email=data["email"],phone=data["phone"], first_name=data["first_name"],last_name=data["first_name"])
u.set_password(data["password"])
u.save()
return u
Everything worked fine, until I dropped the database and run the migrations again. Now, I'm not able to create superuser again.
The error I got is:
TypeError: create_user() missing 1 required positional argument:
'group'
I create superuser from: python3 manage.py createsuperuser from the terminal.
Anyone faced the same problem and is there any solutions to fix the error?
models.py
class CustomUserManager(BaseUserManager):
def create_user(self, email: str, password: str, group: Group, **extra_fields):
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()
if group is not None:
group.user_set.add(user)
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
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)
forms.py
class UserForm(ModelForm):
group = forms.ModelChoiceField(queryset=Group.objects.all())
#temp['group']=request.POST.get('group')
#role = forms.ChoiceField(choices=ROLE_CHOICES, label='', widget=forms.RadioSelect(attrs={}))
class Meta:
model = CustomUser
fields = [
'email',
'password',
'group',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['group'] = ModelChoiceField(
queryset=Group.objects.all(),
empty_label='No group'
)
The create_superuser management command uses the orignal User.objects.create_user function.
You added a positional argument which is required. The create_superuser command does not put any group argument when calling it.
You should make this group argument optional if you really need it.
from typing import Optional
class CustomUserManager(BaseUserManager):
def create_user(self,
email: str,
password: str,
group: Optional[Group] = None,
**extra_fields):
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()
if group is not None:
group.user_set.add(user)
return user