I want a user email to be automatically confirmed if the admin adds a user. Currently the admin adds a user, next select the newly created user and edit manually to confirm user email. I want this process to be automatic from the admin whenever admin creates a user.
accounts/models.py--
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from phonenumber_field.modelfields import PhoneNumberField
User._meta.get_field('email').blank = False
User._meta.get_field('email')._unique = True
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name ='profile')
email_confirmed = models.BooleanField(default=False)
phone_number = PhoneNumberField( blank=True, null=True)
organisation = models.CharField(max_length=30, blank=True)
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
accounts/admin.py
from django.contrib import admin
from django.contrib.auth import admin as upstream
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import Group, User
from django.utils.translation import ugettext, ugettext_lazy as _
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Profile
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile'
fk_name = 'user'
class CustomUserAdmin(UserAdmin):
inlines = (ProfileInline, )
list_select_related = ( 'profile', )
list_display = ('email', 'username', 'first_name', 'last_name', 'is_staff')
#exclude = ('username',)
fieldsets = (
('Personal information', {'fields': ('first_name', 'last_name', 'username', 'email', 'password')}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
('None', {
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2')}
),
)
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(CustomUserAdmin, self).get_inline_instances(request, obj)
def get_ordering(self, request):
return ['-date_joined']
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.user.email_confirmed = True
super(CustomUserAdmin, self).save_model(request, obj, form, change)
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
I have no clue how can I update the model profile email_confirmed to True if the user is created by admin.If not admin then email_confirmed is set to False.
Any help or suggestion is highly appreciated. Thanks in advance.
Related
I created a custom model extending AbstractUser in order to authenticate users by email instad of by username (but not wanting to drop the username, because it will also be used).
This was the first thing I made before running the first migration, everything worked correctly except in the Django admin, when I create a new user, I want these fields to be filled
username
email
password
And the admin only ask me for the username and password. How could I add the email too? Here's my codes
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifier for
authentication instead of username.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User as CustomUser
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('eamil', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, UserAdmin)
What I have to do? It seems that everything is correct, but the required email field is missing. Notice that this only happens when I use the Add User feature in the admin. When I create a superuser or when I login to the admin, everything is working as expected.
UPDATE:
Here's the content of my forms.py
from django.contrib.auth.forms import UserCreationForm
# the user model was customized it should be invoked
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms
from .models import User as CustomUser
class UserChangeForm(auth_forms.UserChangeForm):
class Meta(auth_forms.UserChangeForm.Meta):
model = CustomUser
class UserCreationForm(auth_forms.UserCreationForm):
class Meta(auth_forms.UserCreationForm.Meta):
model = CustomUser
fields = ("username", "email")
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
# the user model was customized it should be invoked
model = get_user_model()
fields = UserCreationForm.Meta.fields + ("email",)
And here the content (updated) of my admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User as CustomUser
from .forms import UserChangeForm, UserCreationForm
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ('email', 'username', 'is_staff', 'is_active',)
list_filter = ('eamil', 'username', 'is_staff', 'is_active',)
form = UserChangeForm
add_form = UserCreationForm
fieldsets = (
(None, {'fields': ('email', 'username', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'username', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, UserAdmin)
But I still have the same problem, I still can't add an email field in /admin/users/user/add/
The UserAdmin class has the attributes form and add_form which point to form classes to be used to edit and create the user respectively. You need to override these form classes and also set these attributes yourself as these two forms are created for the default user model.
Firstly define these custom forms:
from django.contrib.auth import forms as auth_forms
from .models import User as CustomUser
class UserChangeForm(auth_forms.UserChangeForm):
class Meta(auth_forms.UserChangeForm.Meta):
model = CustomUser
class UserCreationForm(auth_forms.UserCreationForm):
class Meta(auth_forms.UserCreationForm.Meta):
model = CustomUser
fields = ("username", "email")
Next set these in your CustomUserAdmin:
from .forms import UserChangeForm, UserCreationForm
class CustomUserAdmin(UserAdmin):
# Your other attributes here
form = UserChangeForm
add_form = UserCreationForm
In your code, I see
admin.site.register(CustomUser, UserAdmin)
but you have to register through your CustomUserAdmin.
Change your admin.py code to
admin.site.register(CustomUser, CustomUserAdmin)
How can I make the Django model available by default, for users (Staff = True), to make available CRUD actions in the admin panel?
I wrote some code based on the Django authentication system:
from django.db import models
from django.contrib.auth.models import AbstractUser
from .manager import CustomUserManager
from django.urls import reverse
from pytils.translit import slugify
class CustomUser(AbstractUser):
username = None # removing username field
email = models.EmailField(unique=True)
is_staff = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
class _TimedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta(object):
abstract = True
class Post(_TimedModel):
title = models.CharField(max_length=100)
body = models.TextField()
slug = models.SlugField(null=False, unique=True)
author = models.ForeignKey('blog.CustomUser', on_delete=models.CASCADE, related_name="post")
objects = models.Manager()
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta(object):
verbose_name = 'Post'
verbose_name_plural = 'Post'
def str(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', kwargs={'slug': self.slug})
Then I created a user registration, added the Post model to the admin panel.
This is the admin.py file
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser, Post
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('email', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, CustomUserAdmin)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'body',)
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Post, PostAdmin)
And this is the file manager.py
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import Permission
class CustomUserManager(BaseUserManager):
def create_user(self, email: str, password, **extra_fields):
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
extra_fields.setdefault('is_staff', True)
permission = Permission.objects.get(name='Can add Post')
user.user_permissions.add(permission)
# user.user_permissions.add(Permission.objects.get(codename="add_post"))
user.save()
return user
def create_superuser(self, email: str, password, **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(email, password, **extra_fields)
For superusers admin panel correctly displays.
But for non-superusers I see this message:
You don’t have permission to view or edit anything.
Please tell me what am I doing wrong? I have to do this by not using groups, this solution must be fully automated.
P.S.: Please, sorry, for my bad English :) I used the Google Translator
Everything I needed, I found here
My forms.py file
class CreateUserForm(UserCreationForm):
phone=PhoneNumberField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'phone']
widgets={
'username':forms.TextInput(attrs={'placeholder':"Username"}),
'email':forms.TextInput(attrs={'placeholder':"Email Address"}),
'password1': forms.PasswordInput(attrs={'placeholder': 'Your Password'}),
'password2': forms.PasswordInput(attrs={'placeholder': 'Confirm Password'}),
'phone':PhoneNumberField(),
}
My models.py file
class CustomerReg(models.Model):
user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name=models.CharField(max_length=200, null=True)
email=models.EmailField(max_length=254)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile=CustomerReg.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
My views.py file
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if(form.is_valid()):
form.save()
user=form.cleaned_data.get['username']
user=User.objects.get(username=user)
phone=form.cleaned_data.get['phone']
user.phone_number=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Upon clicking the register page an error is displayed
AttributeError at /register/
'str' object has no attribute 'User'
So is there no way I can save the data from my form and hence I would have to make new Custom User Model to save phone number of a user on register page?
My admin.py
from django.contrib import admin
from .models import *
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserChangeForm,UserCreationForm
# Register your models here.
admin.site.register(Customer)
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone')
admin.site.register(User, UserAdmin)
If your model is created correctly, the mistake you are making is your variable user is not a User object. The error informs you that user variable represents a string (from the form's input), which does not have User as its attribute. In this case, you might have to do something like
user = User.objects.get(username=user)
in order to assign the User object to variable user.
Now that user is a User object, then, you can do
user.phone_number = phone
user.save()
Please try this:
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username=form.cleaned_data['username']
user=User.objects.get(username=username)
phone=form.cleaned_data['phone']
user.phone=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Are you display phone field for admin then,
admin.py
from .forms import UserChangeForm,UserCreationForm
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone') # You can add field to display field here..
list_filter = ('name')
fieldsets = (
(None, {'fields': ('email')}),
('Personal info', {'fields': ('name','phone')}),
('Permissions', {'fields': ('name',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('name' ,'user','email','email', 'phone')
}),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
I am using UserCreationForm for registration of the user. Added one address filed as mandatory in the code. however whenever the user is registering on the html page the address input is present.In the admin panel for users the address is not present.
form.py
class RegistrationForm(UserCreationForm):
email=forms.EmailField(required=True)
address=forms.CharField(max_length=250,required=True)
class Meta:
model=User
fields=(
'username',
'first_name',
'last_name',
'email',
'address',
'password1',
'password2'
)
def save(self,commit=True):
user=super(RegistrationForm,self).save(commit=False)
user.first_name=self.cleaned_data['first_name']
user.last_name=self.cleaned_data['last_name']
user.email=self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
print("inside views")
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('./login.html')
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
In the user model all the fields are seen in the admin page,just address is not present. However while registering the user, address input is accepted.
I think you need to add this code in your models.py this field you input is required, they are added by default.
Email & Password & last_name & first_name are required by default.
REQUIRED_FIELDS = ['Address', 'SomethingElse']
and then in your admin.py
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
name of your class and your Object you want to add in admin page.
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', 'admin', 'first_name', 'address')
list_filter = ('admin', 'staff', 'active')
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'address')}),
('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': ('email', 'password1', 'password2', 'first_name', 'address', 'active', 'staff', 'admin')}
),
)
search_fields = ('email')
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
# Remove Group Model from admin. We're not using it.
admin.site.unregister(Group)
finally, you can check how I add address field into my project
by this link in Viva-ecommerce-models.py and Follow the Class Address
I am new to django and totally confused so what should i do for these..
Note- list_display = ('email', 'first_name',) 'email', 'first_name' which defined in custom user model User
I am not getting errors but it not registering the Profile model
to admin why?
if i am adding phone from Profile model to list_display = ('email', 'first_name', 'phone') i m getting error (admin.E108) The value of 'list_display[2]' refers to 'phone', which is not a callable, an attribute of 'UserAdmin', or an attribute or method on 'users.User'. How can i add phone in list_display?
I uses post_save_user_model_receiver() to auto create profile when
user is created is it best way to do it?
how can i add all Profile model fields for edit/update in users.admin (which is below).
profile model
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth import get_user_model # or from users.models import User
User = get_user_model()
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
photo = models.ImageField(null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
phone = models.IntegerField(null=True, blank=True)
country = models.CharField(max_length=150, null=True, blank=True)
city = models.CharField(max_length=150, null=True, blank=True)
bio = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return str(self.user.email)
def post_save_user_model_receiver(sender, instance, created, *args, **kwargs ):
if created:
try:
Profile.objects.create(user=instance) # it create those user's profile
except:
pass
post_save.connect(post_save_user_model_receiver, sender=User)
Admin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth import get_user_model
from .models import Profile
User = get_user_model()
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'profile'
# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (ProfileInline,)
list_display = ('email', 'first_name',)
list_filter = ('admin', 'staff', 'active')
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
users.admin file
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 import get_user_model # or from .models import User
from .forms import UserAdminCreationForm, UserAdminChangeForm
# Register your models here.
User = get_user_model() # or 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', 'first_name', 'get_phone', 'last_login', 'date_joined', 'is_admin')
list_filter = ('admin', 'staff', 'active')
list_select_related = ('profile',)
def get_phone(self, instance): # to show the Phone in list display from the Profile Model
return instance.profile.phone
get_phone.short_description = 'Phone'
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal Info', {'fields': ('first_name', 'last_name',)}),
('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': ('email', 'first_name', 'last_name', 'password1', 'password2', )
}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
# Remove Group Model from admin. We're not using it.
admin.site.unregister(Group)