Django Custom User Admin field_sets not showing in admin portal - python

I am creating a custom user class for my data base but I can't get my custom fields to show in the admin portal when adding a new user or changing an existing user. I have registered the app in my settings, migrated the data base, and set the AUTH_USER_MODEL in my settings.py. Thank you!
My admin portal looks like this:
And my files look like this:
models.py
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 _
import secrets
from api_keys.managers import *
class User(AbstractBaseUser, PermissionsMixin):
FULL = 4
MAJOR = 3
MINOR = 2
CONTROLLED = 1
access_groups = [(FULL, 4), (MAJOR, 3), (MINOR, 2), (CONTROLLED, 1)]
username = models.CharField(_('user name'), max_length=50, unique=True)
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=50, blank=True)
last_name = models.CharField(_('last name'), max_length=50, blank=True)
account_name = models.TextField(_('account'), max_length=500, blank=True)
purpose = models.TextField(_('purpose'), max_length=5000, blank=True)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
is_staff = models.BooleanField(_('staff'), default=False)
access_group = models.IntegerField(_('permission group'), choices=access_groups, default=CONTROLLED)
api_key = models.CharField(_('api key'), max_length=100)
delete_on = models.DateField(_('deletion date'), blank=True, null=True)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'access_group']
def save(self, *args, **kwargs):
if not self.api_key:
self.api_key = secrets.token_urlsafe(16)
super(User, self).save(*args, **kwargs)
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def has_access(self, level):
return self.access_group >= level
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
managers.py
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, username, email, password, **extra_fields):
if not username:
raise ValueError('The given user name must be set')
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_staff', False)
return self._create_user(username, email, password, **extra_fields)
def create_superuser(self, username, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_staff', True)
if not extra_fields.get('is_superuser'):
raise ValueError('Superuser must have is_superuser = True')
return self._create_user(username, email, password, **extra_fields)
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from api_keys.forms import UserChangeForm, UserCreationForm
from api_keys.models import User
# Register your models here.
class NewUserAdmin(UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
model = User
list_display = ('username', 'email', 'access_group', 'delete_on', 'api_key')
list_filter = ('username', 'email', 'access_group', 'is_superuser', 'delete_on')
readonly_fields = ['date_joined', 'api_key', 'last_login']
field_sets = (
('User', {'fields': ('username', 'email', 'password', 'access_group')}),
('Permissions', {'fields': (('is_staff', 'is_active'), 'access_group', 'delete_on')}),
)
add_field_sets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', ('password1', 'password2'))
}),
('Permissions', {'fields': (('is_staff', 'is_active'), 'access_group', 'delete_on')})
)
search_fields = ('username', 'email', 'first_name', 'last_name', 'account_name', 'access_group', 'delete_on')
ordering = ('username', 'email', 'first_name', 'last_name', 'access_group', 'account_name', 'delete_on')
admin.site.register(User, NewUserAdmin)
forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from api_keys.models import User
class UserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = User
fields = '__all__'
class UserChangeForm(UserChangeForm):
class Meta(UserChangeForm):
model = User
fields = '__all__'

The layout is controlled by ModelAdmin.fieldsets, not field_sets
class NewUserAdmin(UserAdmin):
...
fieldsets = (
('User', {'fields': ('username', 'email', 'password', 'access_group')}),
('Permissions', {'fields': (('is_staff', 'is_active'), 'access_group', 'delete_on')}),
)

Related

Django: How to create superuser with custom fields?

I have a custom User model in my models.py and custom UserManager as well. My custom User model has username field with changed name to login and same is updated in UserManager as well. Everything goes fine, but when I try to create superuser using command python manage.py createsuperuser, it asks for login but it does not ask for email which at the end gives me this error:
TypeError: UserManager.create_superuser() missing 1 required positional argument: 'email'
My custom User model is:
class User(AbstractBaseUser, PermissionsMixin):
login = models.CharField(max_length=254, unique=True)
email = models.EmailField(max_length=254, unique=True)
first_name = models.CharField(max_length=254, null=True, blank=True)
last_name = models.CharField(max_length=254, null=True, blank=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'login'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
My custom UserManager is:
class UserManager(BaseUserManager):
def _create_user(self, login, email, password, is_staff, is_admin, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
now = timezone.now()
email = self.normalize_email(email)
user = self.model(
login=login,
email=email,
is_staff=is_staff,
is_active=True,
is_admin=is_admin,
last_login=now,
date_joined=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, login, email, password, **extra_fields):
user = self._create_user(login, email, password, False, False, **extra_fields)
user.save(using=self._db)
return user
def create_superuser(self, login, email, password, **extra_fields):
user=self._create_user(login, email, password, True, True, **extra_fields)
return user
and in admin.py I have:
class UserAdmin(BaseUserAdmin):
fieldsets = (
(None, {'fields': ('login', 'email', 'password', 'first_name', 'last_name', 'last_login')}),
('Permissions', {'fields': (
'is_active',
'is_staff',
'is_admin',
'groups',
'user_permissions',
)}),
)
add_fieldsets = (
(
None,
{
'classes': ('wide',),
'fields': ('login', 'email', 'password1', 'password2')
}
),
)
list_display = ('login', 'email', 'first_name', 'last_name', 'is_admin', 'last_login')
list_filter = ('is_staff', 'is_admin', 'is_active', 'groups')
search_fields = ('email', 'login',)
ordering = ('email', 'login',)
filter_horizontal = ('groups', 'user_permissions',)
I just had to add 'email' in the REQUIRED_FIELDS variable in my User model definition. i.e.
I had to change following line:
REQUIRED_FIELDS = []
to
REQUIRED_FIELDS = ['email']

Matching Query Error while trying to make Case Insensitive Usernames in Django

I'm trying to Override the user model to make usernames case insensitive and allow semicolons. I haven't added the code for semicolons yet. I am getting a matching query error while trying to create a superuser.
When I run python manage.py createsuperuser I get a matching query error
Here is my code
models.py
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser, BaseUserManager
)
class UserManager(BaseUserManager):
def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD + '__iexact': username})
def create_user(self, username, password=None, is_active=True, is_staff=False, is_admin=False):
if not username:
raise ValueError("Users must have an username address")
if not password:
raise ValueError("Users must have a password")
user_obj = self.model(
username = self.get_by_natural_key(username)
)
user_obj.set_password(password) # change user password
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self, username, password=None):
user = self.create_user(
username,
password=password,
is_staff=True
)
return user
def create_superuser(self, username, password=None):
user = self.create_user(
username,
password=password,
is_staff=True,
is_admin=True
)
return user
class User(AbstractBaseUser):
username = models.CharField(max_length=255, unique=True)
#full_name = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True) # can login
staff = models.BooleanField(default=False) # staff user non superuser
admin = models.BooleanField(default=False) # superuser
timestamp = models.DateTimeField(auto_now_add=True)
# confirm = models.BooleanField(default=False)
# confirmed_date = models.DateTimeField(default=False)
USERNAME_FIELD = 'username' #username
# USERNAME_FIELD and password are required by default
REQUIRED_FIELDS = [] #['full_name'] #python manage.py createsuperuser
objects = UserManager()
def __str__(self):
return self.username
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def is_staff(self):
return self.staff
def is_admin(self):
return self.admin
def is_active(self):
return self.active
admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
User = get_user_model()
class UserAdmin(BaseUserAdmin):
list_display = ('username', 'admin')
list_filter = ('admin', 'staff', 'active')
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal info', {'fields': ()}),
('Permissions', {'fields': ('admin', 'staff', 'active',)}),
)
# 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', 'password1', 'password2')}
),
)
search_fields = ('username',)
ordering = ('username',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
Here is the error that I'm getting
account.models.DoesNotExist: User matching query does not exist.

Django Custom User Model add property

My model is relatively simple, but I want users to be member of a club. Superusers are not members of a club.
I decided to use a Custom User Model Extending AbstractBaseUser and created the models, managers and everything works fine. Now I want to extend the model by a property.
models.py:
from .managers import MyUserManager
class K2User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
is_staff = models.BooleanField(_('active'), default=True)
# club_name = models.ForeignKey(Clubs, null=True,
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def get_club_name(self):
return self.club_name
def __str__(self):
return self.email
class Clubs(models.Model):
club_name = models.CharField(max_length=32, unique=True)
club_create_date = models.DateTimeField('date created')
club_address = models.CharField(max_length=200)
email = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, verbose_name=_('user'), on_delete=models.CASCADE)
managers.py
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class MyUserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
# club_name = club_name
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', False)
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)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
return self._create_user(email, password, **extra_fields)
how can I add the club name to a normal user, so that he has to be member of a club, but the superuser does not have this property (or just set it null)?
** Edit **
in my admin view I still only see one member for each club - I guess I have to tinker with the admin.py for that?
admin.py:
class K2UserAdmin(UserAdmin):
add_form = K2UserCreationForm
form = K2UserChangeForm
model = K2User
list_display = ('email', 'date_joined', 'is_active',)# 'merchant',)
list_filter = ('email', 'date_joined', 'is_active',)# 'merchant',)
fieldsets = ( (None, { 'fields': ('email', 'password') } ),
('Permissions', { 'fields': ('date_joined', 'is_active') } ), )
add_fieldsets = ( (None, {'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'date_joined', 'is_active') } ), )
readonly_fields = ('date_joined',)
admin.site.register(K2User, K2UserAdmin)
admin.site.register(Clubs)
The best way to implement this is as follows:‌
First of all, you need to create one model between Club and User
(rather than create M2M field). I named it Enrollment.
Put Club and User foreign key this model.
So:
class Enrollment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name=_('enrollment_users'), on_delete=models.CASCADE)
club = models.ForeignKey(Club, related_name=_('enrollment_clubs'), on_delete=models.CASCADE)
If you follow this way, you can do anything you want in this relation in the future.
Hope it help.

django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'username'")

I have the following custom user model implementation in my Django application :
users/models.py
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email: str,
password: str, is_staff: bool,
is_superuser: bool, **extra_fields):
"""Creates and saves a User with the given email and password.
"""
email = self.normalize_email(email)
user = self.model(email=email, is_staff=is_staff, is_active=True,
is_superuser=is_superuser, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email: str, password=None, **extra_fields):
return self._create_user(email, password, False, False, **extra_fields)
def create_superuser(self, email: str, password: str, **extra_fields):
return self._create_user(email, password, True, True, **extra_fields)
class User(AbstractUser, UUIDModel):
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
email = models.EmailField(unique=True, db_index=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
objects = UserManager()
class Meta:
verbose_name = 'user'
verbose_name_plural = 'users'
ordering = ('-date_joined', )
def get_full_name(self):
return "{} {}".format(self.first_name, self.last_name)
def get_short_name(self):
return self.first_name
def get_email(self):
return self.email
def __str__(self):
return "{}".format(self.email)
And my change form in admin.py looks like this :
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from django.contrib.auth.forms import UserChangeForm as DjangoUserChangeForm
from django.contrib.auth.forms import UserCreationForm as DjangoUserCreationForm
from .models import User
# Forms
# ----------------------------------------------------------------------------
class MyUserCreationForm(DjangoUserCreationForm):
class Meta:
model = User
fields = ("email",)
class MyUserChangeForm(DjangoUserChangeForm):
class Meta:
model = User
fields = '__all__'
# ModelAdmins
# ----------------------------------------------------------------------------
#admin.register(User)
class UserAdmin(AuthUserAdmin):
add_form_template = 'admin/auth/user/add_form.html'
model = User
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name',)}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
readonly_fields = ('date_joined', 'last_login')
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('email', 'first_name', 'last_name', 'is_active')
list_filter = ('is_superuser', 'is_active')
search_fields = ('first_name', 'last_name', 'email')
ordering = ('email',)
I have added these two lines in my settings.py files.
AUTH_USER_MODEL = 'users.User'
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",)
I have extended this model to a custom profile model. But when I try to create another user I get the following error django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'username'") . Can anybody help me with this?
I am using Django : Django==2.2 with MySql.
Set
USERNAME_FIELD = 'username'
and test your code.
If everything works then change it.
Add username field in your custom user modal
Because error clearly says duplicate entry for key username which means, you have overrides the default user authentication by email id, so every time you create a user blank username tries to be created. Still, Django won't allow it's default implementation to be unique=True, so you have to override the username attribute also.
class User(AbstractUser):
email = models.EmailField(max_length=100, unique=True)
# add the below one line code
username = models.CharField(max_length=100, unique=False, null=True, default=None)
is_deleted = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']

Django custom user model : User creation issue

I am have created a custom user model to replace username with email. But when I am trying to add user from Django Admin I get error:
Please correct the errors below.
There is no other information with that error message.
The code for custom user:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name="email_address",
max_length=255,
unique=True,
)
name = models.CharField(max_length=255)
is_staff = models.BooleanField(
default=False,
)
is_active = models.BooleanField(
default=True,
)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def get_full_name(self):
return self.name
def __str__(self):
return self.email
Custom User Manager Code:
class UserManager(BaseUserManager):
def _create_user(self, email, password, **kwargs):
if not email:
raise ValueError("Email is required")
email = self.normalize_email(email)
user = self.model(email=email, **kwargs)
user.set_password(password)
user.save()
return user
def create_user(self, email, password=None, **extra_fields):
"""Create and save a regular User with the given email and password."""
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, **kwargs):
kwargs.setdefault('is_staff', True)
kwargs.setdefault('is_superuser', True)
kwargs.setdefault('is_active', True)
if kwargs.get('is_staff') is not True:
raise ValueError("Superuser must have is_staff True")
if kwargs.get('is_superuser') is not True:
raise ValueError("Superuser must have is_superuser True")
return self._create_user(email, password, **kwargs)
and the admin code for same:
class CustomUserAdmin(BaseUserAdmin):
add_form = CustomUserCreationForm
form = CustomUserCreationForm
list_display = ('id', 'email', 'is_superuser')
list_filter = ('is_superuser',)
fieldsets = (
(None, {'fields': ('name', 'email', 'password')}),
('Permissions', {'fields': ('is_superuser', 'is_staff')}),
)
add_fieldsets = fieldsets
search_fields = ('name', 'email')
ordering = ('name', 'email')
filter_horizontal = ()
Custom User Form:
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('name', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = ('name', 'email')
I have tried many changes but couldn't figure out the issue. I would appreciate any help on this.
Change:
class Meta:
model = User
fields = ('name', 'email')
To:
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('name', 'email')

Categories