Create custom user form - django

On Django Admin, the default 'create user' form has 3 fields: username, password and confirm password.
I need to customize the create user form. I want to add the firstname and lastname fields, and autofill the username field with firstname.lastname.
How can I do this?

Something like this should work:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class UserCreateForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'first_name' , 'last_name', )
class UserAdmin(UserAdmin):
add_form = UserCreateForm
prepopulated_fields = {'username': ('first_name' , 'last_name', )}
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('first_name', 'last_name', 'username', 'password1', 'password2', ),
}),
)
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Only add_fieldsets is enough. No need to provide the add_form.
this would be the full code for admin.py, you can read about it in the Django docs here
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class UserAdmin(UserAdmin):
add_fieldsets = (
(
None,
{
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2'),
},
),
)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
As a side note: 'classes':('wide',), sets the style of the field to open or "not collapsed", you can read more about the options for that here

Related

Problem adding user's email in Django admin

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)

Custom Fields in Django not displayed in admin panel

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

Adding required email field to django when creating users with admin

When creating/adding a user with Django admin; how can this be customized?
For example, currently, the username and password are prompted for. However, I'd like to customize this to also have other required fields, such as 'email'?
The Django tutorial isn't clear on admin user auth customization?
Place this in your models.py.
from django.contrib.auth.models import User
User._meta.get_field('email').blank = False
Run makemigrations.
Run migrate.
See the documentation
Example for adding email to form when creating a user. In project admin.py added the following:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
class UserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('username', 'password','email')}),
(_('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': ('username', 'password1', 'password2', 'email')}
),
)
form = UserChangeForm
add_form = UserCreationForm
try:
admin.site.unregister(User)
except NotRegistered:
pass
admin.site.register(User, UserAdmin)
This is how you can customize the user admin:
from django.contrib import admin
from django.contrib.auth import admin as upstream
# custom admin class for the User model, subclassing Django's one
class UserAdmin(upstream.UserAdmin):
add_form_template = ...
add_form = ...
add_fieldsets = ...
# unregister any existing admin for the User model and register mine
try:
admin.site.unregister(User)
except NotRegistered:
pass
admin.site.register(User, UserAdmin)
The parts I left with ... are the customizations you need to do to change the way the admin prompts for user creation.
Look for the original code in django/contrib/auth/admin.py and modify to taste.

How to add fields in extended UserAdmin

I'm trying to create custom user models with their own admins (add and change forms). I'd like to have exactly the same as the original User admin with just the additional fields in the add and change forms.
Anybody could help?
models.py
from django.contrib.auth.models import User
class MyUser1(User):
#add more fields specific to MyUser1
class MyUser2(User):
#add more fields specific to MyUser2
admin.py
from django.contrib.auth.admin import UserAdmin
class MyUser1Admin(UserAdmin):
# how can I add the "fields specific to MyUser1" both in the add
# and the change forms?
admin.site.register(MyUser1, MyUser1Admin)
# same for MyUser2
I had to extend the UserCreationForm and UserChangeForm:
admin.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from django import forms
class MyUser1CreationForm(UserCreationForm):
myuser1_field = forms.CharField()
class Meta:
model = User
fields = ("username", "myuser1_field", "password1", "password2")
class MyUser1ChangeForm(UserChangeForm):
myuser1_field = forms.CharField()
class Meta:
model = User
class MyUser1Admin(UserAdmin):
form = MyUser1ChangeForm
add_form = MyUser1CreationForm
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('myuser1_field', 'first_name', 'last_name', 'email')}),
(_('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', 'myuser1_field', 'password1', 'password2')}
),
)
admin.site.register(MyUser1, MyUser1Admin)
from django.contrib.auth.forms import UserChangeForm
class MyUser1AdminForm(UserChangeForm):
class Meta:
model = MyUser1

Changing User ModelAdmin for Django admin

How do you override the admin model for Users? I thought this would work but it doesn't?
class UserAdmin(admin.ModelAdmin):
list_display = ('email', 'first_name', 'last_name')
list_filter = ('is_staff', 'is_superuser')
admin.site.register(User, UserAdmin)
I'm not looking to override the template, just change the displayed fields & ordering.
Solutions please?
You have to unregister User first:
class UserAdmin(admin.ModelAdmin):
list_display = ('email', 'first_name', 'last_name')
list_filter = ('is_staff', 'is_superuser')
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Maybe this question is also interesting for you: Customizing an Admin form in Django while also using autodiscover
Update tested with Django 3+
So you don't lose data like password encryption and the form itself, perform the import below
from django.contrib.auth.admin import UserAdmin
Define an AdminCustom class as the example and customize with the options you want, overriding the default.
class UserAdminCustom(UserAdmin):
list_display = ('email', 'first_name', 'last_name', 'is_staff', 'is_superuser')
list_filter = ('is_staff', 'is_superuser')
search_fields = ('username', )
And in the end, follow the example mentioned
admin.site.unregister(User)
admin.site.register(User, UserAdminCustom)
As pointed by #haifeng-zhang in the comments, it is useful to extend the default UserAdmin instead.
The official documentation about this can be found here:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
# Define a new User admin
class UserAdmin(BaseUserAdmin):
list_display = ('email', 'first_name', 'last_name')
list_filter = ('is_staff', 'is_superuser')
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)