I customized the Django user model, now I can't link my users to Django groups to give them permissions
from django.db import models
from django.core.validators import RegexValidator
from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser, PermissionsMixin)
from django.db.models.signals import post_save
from django.contrib.auth.models import Group
USERNAME_REGEX = '^[a-zA-Z0-9.+-]*$'
class UserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(username=username, email=self.normalize_email(email))
user.set_password(password)
user.save(using=self._db)
if group is not None:
group.user_set.add(user)
return user
# user.password = password # bad - do not do this
def create_superuser(self, username, email, password=None):
user = self.create_user(username, email, password=password)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
if group is not None:
group.user_set.add(user)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=300, validators=[
RegexValidator(regex=USERNAME_REGEX, message='Username must be alphanumeric or contain numbers',
code='invalid_username')],
unique=True)
email = models.EmailField(max_length=255, unique=True, verbose_name='email address')
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def __str__(self):
return self.username
def get_short_name(self):
# The user is identified by their email address
return self.username
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
Related
I created an app 'accounts' from which I created my CustomUser. Then, I created superuser from the command line successfully. But I can't login to Django Admin. Everytime, it displays "Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive."
This is my accounts.models file, The only one I modified.
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import User
class MyUserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email:
raise ValueError()
if not username:
raise ValueError()
user = self.model(email=self.normalize_email(email), username=username)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password=None):
user = self.create_user(username=username, email=email, password=None)
user.admin = True
user.staff = True
user.superuser = True
user.save()
return user
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=12, primary_key=True, unique=True)
id = models.IntegerField(default=1)
email = models.EmailField(max_length=255, blank=False, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
superuser = models.BooleanField(default=False)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['email']
objects = MyUserManager()
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_superuser(self):
return self.superuser
#property
def is_active(self):
return self.active
Copy-Paste is your problem:
def create_superuser(self, username, email, password=None):
user = self.create_user(username=username, email=email, password=password) # here was password=None
# other staff
I'm currently working on a django project and I have a custom user model in my django app. Custom user authentication is working perfectly, but the issue I'm facing is whenever I'm logging into admin account in the django admin site, it logs out the previous user(let say, user2) and admin being logged in.
How Can I separate their login, so that admin site logins don't interfere with my website login?
Here is my code attached:
Custom User model and its manager:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomerManager(BaseUserManager):
def create_user(self, email, username, name, password=None):
if not email:
raise ValueError('Users must have an email address to register')
if not username:
raise ValueError('Users must have an username address to register')
if not name:
raise ValueError('Users must enter their name to register')
user = self.model(
email = self.normalize_email(email),
username = username,
name=name,
)
user.set_password(password)
user.save(using = self._db)
return user
def create_superuser(self, email, username, name, password=None):
user = self.create_user(
email = self.normalize_email(email),
username = username,
name=name,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Customer(AbstractBaseUser):
# user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
email = models.EmailField(max_length=254, null=True, unique=True)
username = models.CharField(max_length=40, unique=True)
name = models.CharField(max_length=200)
phone = models.CharField(max_length=10, null=True)
address = models.CharField(max_length=500, null=True)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(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)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name']
objects = CustomerManager()
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
Login View:
def loginUser(request):
if request.user.is_authenticated:
return redirect('home')
else:
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.info(request, 'Email or Password didn\'t match!')
context = {}
return render(request, 'accounts/login.html', context)
Logout View:
#login_required(login_url='login')
def logoutUser(request):
logout(request)
return redirect('login')
User Profile View:
#login_required(login_url='login')
def userProfile(request, email):
customer = Customer.objects.filter(email=email).first()
context = {'customer':customer}
return render(request, 'accounts/profile.html', context)
CreateUserForm and LoginForm:
class CreateUserForm(UserCreationForm):
class Meta:
model = Customer
fields = ['username', 'email', 'name', 'password1', 'password2']
# fields = '__all__'
class LoginForm(forms.ModelForm):
password = forms.CharField(label='password', widget=forms.PasswordInput)
class Meta:
model = Customer
fields = ['email', 'password']
def clean(self):
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(email=email, password=password):
raise forms.ValidationError('Incorrect Login')
When User3 is logged in and admin is not logged in:
As soon as admin logged in:
User3 automatically logs out and admin logs in..
I have created a model for an AbstractBaseUser, but am struggling to authenticate it.
Here is my model:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.password_validation import validate_password
from uuid import uuid4
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, is_staff=False, is_superuser=False, **other_fields):
if not email:
raise ValueError('Email address must be specified')
if not password:
raise ValueError('Password must be specified')
user = self.model(
email=self.normalize_email(email),
is_staff=is_staff,
is_superuser=is_superuser,
**other_fields
)
validate_password(password)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password, **other_fields):
return self._create_user(email, password, False, False, **other_fields)
def create_superuser(self, email, password, **other_fields):
return self._create_user(email, password, True, True, **other_fields)
class CustomUser(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid4(), editable=False, unique=True)
email = models.EmailField(max_length=254, unique=True)
is_superuser = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_premium = models.BooleanField(default=False)
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
display_name = models.CharField(max_length=40)
date_of_birth = models.DateField()
currency = models.CharField(max_length=3)
date_joined = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
REQUIRED_FIELDS = ['first_name', 'display_name', 'date_of_birth', 'currency']
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
objects = CustomUserManager()
def get_full_name(self):
return ("%s %s" % (self.first_name, self.last_name)) if self.last_name != '' else self.first_name
def get_short_name(self):
return self.first_name
def __str__(self):
return "%s %s - %s" % (self.first_name, self.last_name, self.email)
Here is my view:
from django.contrib.auth import authenticate
from django.http import HttpResponse
def user_login(request):
user = authenticate(request, email=request.POST['email'], password=request.POST['password'])
if user is not None:
login(request, user)
else:
HttpResponse("Invalid email/password pair", status=401)
return HttpResponse()
And, in my settings.py, I have the following:
AUTH_USER_MODEL = 'myapp.CustomUser'
The issue is that, whenever I send create a user and send a request to user_login, the authenticate method always returns None, thus triggering the HttpResponseBadRequest. The email in the request matches what is in the database, and the password matches the password I used to create the user (I've spent longer than I care to admit using print statements to verify that).
Is there something I am missing? Do AbstractBaseUsers require something extra for authentication?
The comment by Iain Shelvington clued me into the answer.
The test I was using to test the authentication was creating the user by saving it directly to the database like this:
from .models import CustomUser
user_data = generate_user()
CustomUser(**user_data).save()
Because the user was being saved directly to the database, its password never got hashed.
I needed to instead create the user like this:
from Django.test import Client
from .models import CustomUser
user_data = generate_user()
client = Client()
client.post('/endpoint/used/to/create/user', user_data)
AttributeError at /register/
Manager isn't available; 'auth.User' has been swapped for 'accounts.Account'
I'm trying to create a registration form but getting the AttributeError.
How can to avoid the error?
Here is the code in of my custom model in
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
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 a 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),
password=password,
username=username,
)
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, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
about = models.TextField(('about'), max_length=500, blank=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 = MyAccountManager()
def __str__(self):
return self.email
# For checking permissions. to keep it simple all admin have ALL permissons
def has_perm(self, perm, obj=None):
return self.is_admin
# Does this user have permission to view this app? (ALWAYS YES FOR SIMPLICITY)
def has_module_perms(self, app_label):
return True
views.py
from django.shortcuts import render
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from .forms import *
from django.contrib.auth import get_user_model
def register_view(request, *args, **kwargs):
form = CreateUserForm(request.POST or None)
if form.is_valid():
user = form.save(commit=True)
user.set_password(form.cleaned_data.get('password1'))
context = {
'form':form,
'btn_label':'Register',
'title':'Register'
}
return render(request, 'auth/auth.html', context)
I updated the setting.py file and set the following link to the Account model in accounts app
settings.py
AUTH_USER_MODEL = 'accounts.Account'
Traceback
Exception Type: AttributeError at /register/
Exception Value: Manager isn't available; 'auth.User' has been swapped for 'accounts.Account'
I have created a Custom User Model(I am new to this Curtom thing) And I got this error at login. NOT NULL constraint failed: users_usermodel.password. I don't understand what to do. Here is my models.py and views.py
I changes the login to mylogin because I thought the function might contrdict the django login funtion. but nothing changed. Please help me solve my problem
Models.py
# Custom User Model Code
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email,first_name, last_name, password=None):
"""
Creates and saves a User with the given email, favorite color
and password.
"""
if not email:
raise ValueError('Users must have an email address')
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,first_name, last_name, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
first_name=first_name,
last_name=last_name,
)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserModel(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
first_name = models.CharField(max_length=20, default='')
last_name = models.CharField(max_length=20, default='')
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name','last_name']
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
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.contrib.auth import logout
from .models import UserModel
# Create your views here.
def profile(request):
return render(request, '/users/profile.html')
def register(request):
if request.method == 'POST':
first_name = request.POST.get('firstname')
last_name = request.POST.get('lastname')
email = request.POST.get('email')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if password1 == password2:
user = UserModel(first_name=first_name, last_name=last_name, email=email, password=password1)
user.save()
return render(request, 'users/login.html')
else:
message = 'Invalid Credentials'
return redirect('users/register.html', {'message':message})
return render(request,'users/register.html')
def login(request):
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
print(password)
try:
user = UserModel.objects.get(email=email)
if password == user.password:
return redirect(request, 'themes/index.html')
else:
message = 'Invali Credentials'
return render(request,'users/login.html', {'message':message})
except:
message = 'Invalid Credentials'
return render(request,'users/login.html', {'message':message})
return render(request,'users/login.html')
def userlogout(request):
logout(request)
return redirect('home')
In your manager,you have password set as None,that's y it's throwing this error,just set your function like the following _create_user(self,email,first_name,last_name,password):
this should fix your problem,and also don't forget to setup AUTH_USER_MODEL in settings.