UserCreationForm KeyError 'email' in Registration page - django

Im learning django and im trying to understand the registration progress with an UserCreationForm and a CreateView, I want to use an email as field on the registration form but they keep poping an error about KeyError 'email' on my form.
forms.py
from django import forms
from accountApp.models import Profile
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username','first_name', 'last_name', 'email')
class CreateUserForm(UserCreationForm):
fields = ('username', 'email', 'password1', 'password2')
model = get_user_model()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Usuario'
self.fields['email'].label = 'Email'
views.py
from django.urls import reverse, reverse_lazy
from . import forms
class RegistrationPage(CreateView):
template_name = 'accountApp/register.html'
success_url = reverse_lazy('accApp:profilepage')
form_class = forms.CreateUserForm
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
def __str__(self):
return self.user.username
IMG 01 error
IMG 02 error

It is failing here
self.fields['email'].label = 'Email'
Here you can see that UserCreationForm form you are inheriting from has no field email.
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and
password.
"""
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
password1 = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
help_text=password_validation.password_validators_help_text_html(),
)
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput,
strip=False,
help_text=_("Enter the same password as before, for verification."),
)
class Meta:
model = User
fields = ("username",)
field_classes = {'username': UsernameField}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self._meta.model.USERNAME_FIELD in self.fields:
self.fields[self._meta.model.USERNAME_FIELD].widget.attrs.update({'autofocus': True})
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def _post_clean(self):
super()._post_clean()
# Validate the password after self.instance is updated with form data
# by super().
password = self.cleaned_data.get('password2')
if password:
try:
password_validation.validate_password(password, self.instance)
except forms.ValidationError as error:
self.add_error('password2', error)
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
You can add fields if you want to
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
and override save method.

Related

Conditionally require password when creating user in Django Admin page

I am using LDAP for authentication in my Django app so when adding a user in the admin page I don't need to set a password since the user will be authenticated against the LDAP backend. I'd like to modify the 'Add user' page in the admin views to have a boolean selector to identify when I am trying to add an LDAP user so that the password field is not required. I'd like to retain the option of supplying a password in case I need to add a local user that authenticates against Django's backend.
Here is what I've cobbled together so far:
models.py
Modified the save method so that the user gets populated in the CustomUser model if isLdap is True.
class CustomUser(AbstractUser):
pass
isLdap = models.BooleanField(default=False)
def save(self, *args, **kwargs):
if self.isLdap:
user = LDAPBackend().populate_user(self.username)
else:
super().save(*args, **kwargs)
def __str__(self):
return self.username
admin.py
I successfully added a check box to identify if the new user is an LDAP user but the value isn't being saved to the CustomUser model and I need to change save_model so it saves the actual password if it is valid otherwise set_unusable_password().
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
add_fieldsets = (
(None, {
'description': (
"Enable 'IsLdap' if the username is a LAN ID. "
),
'fields': ('username','isLdap'),
}),
('Password', {
'fields': ('password1', 'password2'),
}),
)
model = CustomUser
def save_model(self, request, obj, form, change):
obj.set_unusable_password()
super(UserAdmin, self).save_model(request, obj, form, change)
admin.site.register(CustomUser, CustomUserAdmin)
forms.py
Not sure if this is the spot or how to do it, but I think here is where I need to conditionally set ....required = False if isLdap is True.
class CustomUserCreationForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
self.fields['password1'].required = False
self.fields['password2'].required = False
def clean_password2(self):
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
Appreciate any help in getting this code functional!
Here's what I ended up doing:
Models.py
from django.db import models
from django.contrib.auth.models import (AbstractUser, BaseUserManager, )
from django_auth_ldap.backend import LDAPBackend
from django.dispatch import receiver
# Create your models here.
class CustomUserManager(BaseUserManager):
def create_user(self, username, is_ldap, password, **extra_fields):
if not username:
raise ValueError(_('The username must be set'))
user = self.model(username=username,
is_ldap=is_ldap,
**extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, is_ldap, password=None, **extra_fields):
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(username, is_ldap, password, **extra_fields)
class CustomUser(AbstractUser):
is_ldap = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['is_ldap']
objects = CustomUserManager()
def __str__(self):
return self.username
#receiver(models.signals.post_save, sender=CustomUser)
def user_created(sender, instance, created, **kwargs):
if created and instance.is_ldap:
user = LDAPBackend().populate_user(instance.username)
admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from .models import CustomUser
class CustomUserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password1'].required = False
self.fields['password2'].required = False
class Meta:
model = CustomUser
fields = ('username','is_ldap',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
is_ldap = self.cleaned_data.get("is_ldap")
if is_ldap:
if password1 or password2:
raise ValidationError("Leave password fields empty for an LDAP user")
else:
if not password1 or not password2:
raise ValidationError("Passwords don't match")
elif password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
if self.cleaned_data['is_ldap']:
user.set_unusable_password()
else:
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class CustomUserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
disabled password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = CustomUser
fields = ('username','is_ldap',)
class CustomUserAdmin(UserAdmin):
# The forms to add and change user instances
form = CustomUserChangeForm
add_form = CustomUserCreationForm
model = CustomUser
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('username', 'first_name', 'last_name', 'is_staff', 'is_active', 'is_ldap',)
# list_filter = ('username', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('username', 'is_ldap', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name')}),
('Permissions', {'fields': ('is_superuser','groups')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'is_ldap', 'password1', 'password2'),
}),
)
search_fields = ('username',)
ordering = ('username',)
filter_horizontal = (['groups',])
admin.site.register(CustomUser, CustomUserAdmin)

default groups& permissions not working for abstract base user with permissions mixin in django

I am working with AbstractBase user. I have created users and groups. After I assign group to user, if I login with that user , the user has access to the complete admin site with all the CRUD operations.
I have a created a product group with add-delete-edit-view permissions(default) and assigned a user to it. But when this user logins to the admin site, he has access to all the other items of the site as well.
How do I make sure the logged in user can access only the items from assigned groups /permissions???
#managers.py
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
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_superuser', False)
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_active', True)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_active', 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)
#models.py
from __future__ import unicode_literals
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from .managers import UserManager
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
is_superuser = models.BooleanField(_('is_superuser'), default=True)
is_staff= models.BooleanField(_('is_staff'), default=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
'''
Returns the first_name plus the last_name, with a space in between.
'''
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns the short name for the user.
'''
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
'''
Sends an email to this User.
'''
send_mail(subject, message, from_email, [self.email], **kwargs)
#forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
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
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
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(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'password', 'is_active','is_superuser','is_staff')
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"]
#admin.py
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminCreationForm, UserAdminChangeForm
from .models import User
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'is_superuser')
list_filter = ('is_superuser',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ()}),
('Permissions', {'fields': ('is_superuser','groups')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
typo : password instead of password1
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
and you are also missing this methods in you User Model:
def has_perm(self, perm, obj=None):
return True # self.is_admin
def has_module_perms(self, app_label):
return True

Django not creating user after extending AbstractUser

I tried extending my AbstractUser to allow more user types and to also allow users to create an account using their email address. However, I have been facing issues with user creation form on the frontend despite the fact that my Django admin works perfectly as I can create or sign in using email address instead of a username.
In addition, I noticed that anytime I submit the account creation form, the values auto-populate my browser's address bar, and of course, the user won't be created. I don't know if I can get some help to this issue, maybe I am simply missing a very vital step.
Below is a sample of auto-populated values shown in my browser's address bar when I (users) submit the form
http://127.0.0.1:8000/signup/company/?csrfmiddlewaretoken=7AC4rKoyFsYTkcOKLpaiREAYZQwu1i3hGlF51I3Svs65Kf4Fkc64j25YZAN2pKE4&email=jyak%40yahoo.com&password1=oluwasegun01&password2=oluwasegun01&name=Hedge&number_of_employees=20&country=1&phone=012345678901
Below are my codes:
Models.py
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin, AbstractUser
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from accounts.managers import CustomUserManager
from accounts.validators import validate_digit_length
from data.models import Country
class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
#some other user types
username = None
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(_('startup name'), max_length=250, blank=True)
number_of_employees = models.IntegerField(_('no of employees'), blank=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
phone = models.CharField(_('phone number'), max_length=11, validators=[validate_digit_length],
default='08012345678')
def __str__(self):
return self.name
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.core.exceptions import ValidationError
from django.db import transaction
from django.forms import EmailInput, TextInput
from data.models import Country
from .models import User, Company
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = User
fields = ('email',)
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = ('email',)
class CompanySignUpForm(UserCreationForm):
email = forms.EmailField(widget=EmailInput(attrs={'placeholder': 'official company email'}))
name = forms.CharField(widget=TextInput(attrs={'placeholder': 'company name'}))
number_of_employees = forms.CharField(widget=TextInput(attrs={'placeholder': 'number of employees'}))
phone = forms.CharField(widget=TextInput(attrs={'placeholder': 'contact number'}))
password1 = forms.CharField(label='Password', widget=forms.PasswordInput(attrs={'placeholder': 'password'}))
password2 = forms.CharField(label='Confirm password',
widget=forms.PasswordInput(attrs={'placeholder': 'confirm password'}))
country = forms.ModelChoiceField(queryset=Country.objects.all(), required=True)
class Meta:
model = User
fields = ('email', 'password1', 'password2', 'name', 'number_of_employees', 'country', 'phone', )
def clean_password2(self):
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 clean_email(self):
email = self.cleaned_data.get("email")
if User.objects.filter(email=email).exists():
raise ValidationError("Email already exists.")
return email
def save(self, commit=True):
company = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
Views.py
def company_signup(request):
if request.method == 'POST':
form = CompanySignUpForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'accounts/templates/signup_success.html')
else:
messages.warning(request, 'Account creation failed. Please check for possible errors')
else:
form = CompanySignUpForm()
return render(request, 'accounts/templates/company_signup.html', context={
'title': _('Create Account'),
'form': form,
})

Why is django throwing a system error?

I am building a custom user that uses an email as a username.
When I run the server to create a custom admin, I get this error
class 'user.admin.UserAdmin'>: (admin.E116) The value of
'list_filter[0]' refers to 'is_staff', which does not refer to a
Field.
Here is my code for the admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import BaseUser
class UserCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput
)
password2 = forms.CharField(
label='Password confirmation',
widget=forms.PasswordInput
)
class Meta:
model = BaseUser
fields = ('email',)
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 != password2:
raise forms.ValidationError('Password do not match')
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""
A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = BaseUser
fields = (
'email',
'password',
'user_first_name',
'user_last_name',
'user_mobile',
'is_a_student',
)
def clean_password(self):
return self.initial["password"]
class UserAdmin(UserAdmin):
#Forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
#The fields to be used in displaying User model.
#These overried the definitions on the base UserAdmin
#That reference specific fields on auth.User
list_display = (
'email',
)
list_filter = ('is_staff',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': (
'user_first_name',
'user_last_name',
'user_mobile',
)}),
('Permission', {'fields': (
'is_a_student',
)})
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': (
'email',
'password1',
'password2',
'user_first_name',
'user_last_name',
'user_mobile',
'is_a_student',
)}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
#Register the new UserAdmin
admin.site.register(BaseUser, UserAdmin)
admin.site.unregister(Group)
Here is the models.py
from django.db import models
from django.core.validators import RegexValidator
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.core.mail import send_mail
from django.utils.http import urlquote
from django.utils.translation import ugettext_lazy as _
from django.core.mail import send_mail
from django.core.files.storage import FileSystemStorage
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser, PermissionsMixin
)
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password
"""
user = self.create_user(
email=email,
password=password,
)
user.is_superuser = user.is_staff = True
user.save(using=self._db)
return user
class BaseUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email',
max_length=255,
unique=True,
)
user_first_name = models.CharField(max_length=30)
user_last_name = models.CharField(max_length=50)
mobile_regex = RegexValidator(regex=r'^\+?1\d{9,15}$', message="Please enter a max of 10 digits :)")
user_mobile = models.CharField(validators=[mobile_regex], blank=True, max_length=10)
is_a_student = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"""
Does the user have a specific permission?
"""
return True
def is_student(self):
return self.is_a_student
#property
def is_staff(self):
"""
Is the user a member of staff?
"""
return self.is_staff
def emai_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
Options done
- I already took out all of the is_staff attribute in admin.py and still got an error.
- Refactored it many times to check if the problem is in different areas of my code.
At this point I am stuck. Could someone please help debug this?
#list_filter = ('is_staff',)
list_filter = ('is_admin',)
You have to add this line which will filter your data in django-admin I had the same issue I resloved it by doing this in my admin.py file or for more brief information you can check out this wonderful tutorial:
Custom Django User Admin
`list_filter = ('admin', 'staff', or anything which you want to add in filter list)`
#property
def is_staff(self):
"""
Is the user a member of staff?
"""
return self.is_staff
The above code creates a recursive execution which caused the error.
#property
def is_admin(self):
"""
Is the user a member of staff?
"""
return self.is_staff
As Django "talks" about field i would check the model in a first review
i couldn't find any password or password1 nor password2 field in the model for example.

Can't get Django custom user model to work with admin

I created a custom user model (following this writeup), and I manage to get the signup and login to work. However, I'm having trouble logging into admin. Specifically, even after "successfully" created a superuser, I'm unable to login to the admin and got error message: "Please enter the correct email address and password for a staff account. Note that both fields may be case-sensitive."
For the sake of completeness, I'm attaching the following code. I know it's a lot but any suggestion would be helpful. Thanks!!
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(email=self.normalize_email(email),
)
user.is_active = True
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email=email, password=password)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
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
custom backend in backends.py
from django.conf import settings
from django.contrib.auth.models import check_password
from account.models import User
class EmailAuthBackend(object):
"""
A custom authentication backend. Allows users to log in using their email address.
"""
def authenticate(self, email=None, password=None):
"""
Authentication method
"""
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
else:
print('Password not correct')
except User.DoesNotExist:
print('User does not exist')
return None
def get_user(self, user_id):
try:
user = User.objects.get(pk=user_id)
if user.is_active:
return user
return None
except User.DoesNotExist:
return None
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, ReadOnlyPasswordHashField
from .models import User as AuthUser
from django import forms
class CustomUserCreationForm(UserCreationForm):
""" A form for creating new users. Includes all the required fields, plus a repeated password. """
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)
class Meta(UserCreationForm.Meta):
model = AuthUser
fields = ('email',)
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 do not 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 CustomUserChangeForm(UserChangeForm):
password = ReadOnlyPasswordHashField(label="password",
help_text="""Raw passwords are not stored, so there is no way to see this
user's password, but you can change the password using <a href=\"password/\">
this form</a>.""")
class Meta(UserChangeForm.Meta):
model = AuthUser
fields = ('email', 'password', 'is_active', 'is_superuser', 'user_permissions')
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"]
class AuthUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
list_display = ('email', 'is_superuser')
list_filter = ('is_superuser',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_active', 'is_superuser')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_superuser')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ('groups', 'user_permissions',)
admin.site.register(AuthUser, AuthUserAdmin)
The attribute that controls access to the admin is is_staff, not is_admin.
If you wanted to keep your current field for whatever reason, you could define an is_staff() method and make it a property.
Upgrade your Django to 1.9 version. I had resolved this issue using:
$ pip install django==1.9b1