I have extended django user model and customized it using AbstractBaseUser method. and now in admin page password field showing password as plain text. how i solve this ? i need a answer how to solve this without implementing custom form.
model.py
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length = 30, unique = True,
help_text = _('Required. 30 characters or fewer. Letters, numbers and '
'#/./+/-/_ characters'),
validators = [
validators.RegexValidator(re.compile(
'^[\w.#+-]+$'), _('Enter a valid username.'), 'invalid')
])
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)
is_active = models.BooleanField(_('active'), default = True,
help_text = _('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
is_staff = models.BooleanField(_('staff status'), default = False,
help_text = _('Designates whether the user can log into this admin '
'site.'))
is_admin = models.BooleanField(default = False)
date_joined = models.DateTimeField(_('date joined'), default = timezone.now)
# avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
age = models.IntegerField(_('age'), default = 0)
address = models.CharField(_('address'), max_length = 100,blank = True)
user_type = models.ForeignKey( UserType , default = '0',)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
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)
admin.py
class UserAdmin(admin.ModelAdmin):
class Meta:
models = User
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email', 'address', 'age')}),
(_('Permissions'), {'fields': ('user_type','is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2','email','address', 'age', 'user_type')}
),
)
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff','user_type')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('username', 'first_name', 'last_name', 'email')
ordering = ('username',)
filter_horizontal = ('groups', 'user_permissions',)
It Works for me, import BaseUserAdmin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
search_fields = ['username', 'first_name', 'last_name',]
list_display = ('username', 'first_name', 'last_name',)
filter_horizontal = ('groups', 'user_permissions')
fieldsets = (
('Usuario', {'fields': ('username', 'password')}),
('Información Personal', {'fields': (
'first_name',
'last_name',
'email',
)}),
('Permisos', {'fields': (
'is_active',
'is_staff',
'is_superuser',
'groups',
'user_permissions'
)}),
)
admin.site.register(User, UserAdmin)
Related
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']
When i remove the thick from the 'Referans Kodu Doğrulaması', users become unvisible in admin panel. I've tried almost every parameters of BooleanField but i couldn't change the situation. I thought former migrations result it altough i changed it too but nothing changed.
# admin.py
class UserAdmin(BaseUserAdmin):
actions = [ban_users]
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'profession', 'phonenumber', 'birthdate', 'search_history')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser','is_email_verified', 'is_completed_referance_signup', 'newsletter_subscription', 'referencecode' ,
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined','NumberOfEdits','Newsletterlog')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
list_display = ('email', 'first_name', 'last_name','profession','phonenumber', 'is_staff','date_joined', 'NumberOfEdits')
search_fields = ('email', 'first_name', 'last_name')
ordering = ('email',)
readonly_fields = ('NumberOfEdits','Newsletterlog')
# models.py
class User(AbstractUser):
"""User model."""
username = None
referencecode =
models.ForeignKey('ReferenceCode',on_delete=models.SET_NULL,null=True,
verbose_name='Referans Kodu', blank=True , error_messages={'invalid':"Geçersiz referans kodu."})
is_completed_referance_signup = models.BooleanField(verbose_name= 'Referans Kodu Doğrulaması' , blank = True , default = False )
email = models.EmailField(verbose_name='E-Posta Adresi', unique=True)
profession = models.ForeignKey('Profession',on_delete=models.SET_NULL,null=True, verbose_name='Meslek')
birthdate = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True)
is_email_verified = models.BooleanField(verbose_name= 'E-Posta Doğrulaması', default=False)
phonenumber = models.CharField('Cep Telefonu Numarası',max_length=20 , blank=True, null=True)
newsletter_subscription = models.BooleanField(verbose_name= 'E-Posta Haber Aboneliği', default=False)
search_history = models.ManyToManyField(SearchHistory, blank=True, verbose_name="Arama Geçmişi")
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
if self.first_name == '' and self.last_name == '':
return self.email
return self.first_name +" " + self.last_name
def save(self, is_admin_edit = False, *args, **kwargs):
if self.pk:
if not get_user_model().objects.get(pk=self.pk).newsletter_subscription == self.newsletter_subscription:
nll = NewsletterLog()
nll.user = self
nll.newsletter_subscription = self.newsletter_subscription
if is_admin_edit:
nll.is_admin_edit = True
nll.save()
super(User, self).save(*args, **kwargs)
else:
super(User, self).save(*args, **kwargs)
if self.newsletter_subscription:
nll = NewsletterLog()
nll.user = self
nll.newsletter_subscription = self.newsletter_subscription
if is_admin_edit:
nll.is_admin_edit = True
nll.save()
I'm working on a project using Python(3.7) and Django(2.2) in which I have implemented my models for multiple user types with custom user model as the base model. Everything working fine except the admin side, I have register these modles to admin but when I try to add an object from admin interface it's giving an error.
Here's what I have tried so far:
From models.py:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
title = models.CharField(max_length=255, blank=False)
user_type = models.CharField(max_length=255, choices=USER_TYPE, blank=False)
gender = models.CharField(max_length=255, choices=CHOICES, blank=False)
contenst = models.CharField(max_length=255, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = 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 = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['password']
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class PersonalBelow18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
dob = models.DateField(blank=False)
customer_id = models.BigIntegerField(blank=False)
collection_use_personal_data = models.BooleanField(blank=False)
reference_identities = models.ForeignKey(Identities, blank=False, on_delete=models.CASCADE, related_name='refs')
def __str__(self):
return self.user.email+'\'s account with ' + str(self.customer_id)
class PersonalAbove18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
dob = models.DateField(blank=False)
customer_id = models.BigIntegerField(blank=False)
contact_email = models.EmailField(blank=False)
reference_identities = models.ForeignKey(Identities, blank=False, on_delete=models.CASCADE)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
collection_use_personal_data = models.BooleanField(blank=False)
def __str__(self):
return self.user.email+'\'s account with ' + str(self.customer_id)
class Parent(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contact_email = models.EmailField(blank=False)
customer_id = models.BigIntegerField(blank=True)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
collection_use_personal_data = models.BooleanField(blank=False)
class GroupContactPerson(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contact_email = models.EmailField(blank=False)
customer_id = models.BigIntegerField(blank=False)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
department = models.CharField(max_length=255, blank=False)
address = models.TextField(max_length=255, blank=False)
and here's how I register these models to admin:
From admin.py:
class UserAdmin(BaseUserAdmin):
fieldsets = (
(None, {'fields': ('email', 'password', 'title', 'user_type',
'gender', 'contenst', 'last_login')}),
('Permissions', {'fields': (
'is_active',
'is_staff',
'is_superuser',
'groups',
'user_permissions',
)}),
)
add_fieldsets = (
(
None,
{
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')
}
),
)
list_display = ('email', 'title', 'is_staff', 'last_login')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ('groups', 'user_permissions',)
admin.site.register(User, UserAdmin)
admin.site.register(PersonalBelow18)
admin.site.register(PersonalAbove18)
admin.site.register(Parent)
admin.site.register(GroupContactPerson)
The Parent and GroupContactPerson models are working well on admin side but the when I try to add an object for PersonalBelow18 & PersonalAbove18 models, it gives the following error as:
TypeError: str returned non-string (type int)
Here's how I debug this problem in these models:
I start removing all fields one-by-one
Remove a field from model & form and perform migrations
Then test the admin
Then I found that when I removed the reference_identities field it start working, so I get that this model was returning an integer, so I fixed that model and it fix the issue.
In short, it's a good approach to find a path to the actual place of problem by removing fields one-by-one and test the admin.
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']
Folks,
I'm trying to create my own User model by extending the AbstractBaseUser model provided by Django.
However, I keep on getting the following error when migrating:
ValueError: The field admin.LogEntry.user was declared with a lazy reference to '<app_name>.user', but app '<app_name>' doesn't provide model 'user'.
What I have done so far is the following:
In app/models.py added CustomUser class together with CustomUserManager with relevant fields and all.
In app/admin.py I've added this:
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from <app_name>.models import CustomUser
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = ('email',)
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('email',)
def clean_username(self):
username = self.cleaned_data["username"]
try:
get_user_model().objects.get(username=username)
except get_user_model().DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
fieldsets = (
(None, {'fields': [('username', 'password'),]}),
(('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
admin.site.register(CustomUser, CustomUserAdmin)
Apart from that there is this added to seetings.py
AUTH_USER_MODEL = '<app_name>.CustomUser'
Everything that I found so far suggests that the above given code should make this work, but it doesn't. I spent like 4-5 hours already and I still can't get my head around it. Someone please help
Create your User model like so:
from django.core import validators
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import UserManager
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=75, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'underscores characters'),
validators=[
validators.RegexValidator(re.compile('^[\w]+$'),
_('Enter a valid username.'), 'invalid')
])
first_name = models.CharField(_('first name'), max_length=254, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), max_length = 254, unique = True, null = True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['first_name']
def get_full_name(self):
return self.name
def get_short_name(self):
return self.username
Don't forget to add your custom fields!
Use a custom admin like so:
#admin.register(models.User)
class CustomUserAdmin(UserAdmin):
list_display = ('name', 'username', 'is_staff', )
list_filter = ('is_staff', )
search_fields = ('first_name', 'last_name', 'username', )
readonly_fields = ('date_joined', 'last_login', )
fieldsets = (
(None, {
'fields': ('username', 'password')
}),
("Personal Information", {
'fields': ('first_name', 'last_name', 'email')
}),
("Permissions", {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')
}),
("Important Dates", {
'fields': ('last_login', 'date_joined')
}),
)
Then finally add it to your settings:
AUTH_USER_MODEL = '<app_name>.User'
A working demonstration can be found in my GitHub repository.