I have extended User model for django, using AbstractUser method. The problem is, my custom fields do not show in django admin panel.
My models.py:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
is_bot_flag = models.BooleanField(default=False)
My admin.py:
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
Thanks
If all you want to do is add new fields to the standard edit form (not creation), there's a simpler solution than the one presented above.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
class CustomUserAdmin(UserAdmin):
fieldsets = (
*UserAdmin.fieldsets, # original form fieldsets, expanded
( # new fieldset added on to the bottom
'Custom Field Heading', # group heading of your choice; set to None for a blank space instead of a header
{
'fields': (
'is_bot_flag',
),
},
),
)
admin.site.register(User, CustomUserAdmin)
This takes the base fieldsets, expands them, and adds the new one to the bottom of the form. You can also use the new CustomUserAdmin class to alter other properties of the model admin, like list_display, list_filter, or filter_horizontal. The same expand-append method applies.
You have to override UserAdmin as well, if you want to see your custom fields. There is an example here in the documentation.
You have to create the form for creating (and also changing) user data and override UserAdmin. Form for creating user would be:
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = '__all__'
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 save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
You override UserAdmin with:
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
add_form = UserCreationForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'first_name', 'last_name', 'is_bot_flag', 'password1', 'password2')}
),
)
and then you register:
admin.site.register(User, UserAdmin)
I pretty much copy/pasted this from documentation and deleted some code to make it shorter. Go to the documentation to see the full example, including example code for changing user data.
The quickest way to show your extra fields in the Django Admin panel for an AbstractUser model is to unpack the UserAdmin.fieldsets tuple to a list in your admin.py, then edit to insert your field/s in the relevant section and repack as a tuple (see below).
Add this code in admin.py of your Django app
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
fields = list(UserAdmin.fieldsets)
fields[0] = (None, {'fields': ('username', 'password', 'is_bot_flag')})
UserAdmin.fieldsets = tuple(fields)
admin.site.register(User, UserAdmin)
Note:
list(UserAdmin.fieldsets) gives the following list:
[ (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')})
]
These fields are by default in Django user models, and here we are modifying the first index of the list to add our custom fields.
Try this...
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
phone_number = models.CharField(max_length=12)
settings.py : Add below line of code in settings.py
AUTH_USER_MODEL = 'users.CustomUser'
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = '__all__'
admin.py
from django.contrib import admin
from .models import CustomUser
from .forms import CustomUserCreationForm
from django.contrib.auth.admin import UserAdmin
# Register your models here.
class CustomUserAdmin(UserAdmin):
model = CustomUser
add_form = CustomUserCreationForm
fieldsets = (
*UserAdmin.fieldsets,
(
'Other Personal info',
{
'fields': (
'phone_number',
)
}
)
)
admin.site.register(CustomUser, CustomUserAdmin)
After all are done then run below command in terminal
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Related
I am developing a website on django. When I am trying to delete a user via admin panel i get an error. I can change e.g. staff status (while still getting an error, but changes are getting apllied) The code is below:
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
emailSpam = models.BooleanField(default=True)
email = models.EmailField('email', unique=True)
first_name = None
last_name = None
confirmedEmail = models.BooleanField(default=False)
REQUIRED_FIELDS = ["emailSpam"]
forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('email',)
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = ('email',)
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import User
class Admin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = User
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(User, Admin)
Possible solutions
There are three things that might be causing the issue, at least as far as I can tell. The first you already discounted. I hope it's the second solution, since that will be easier, but I fear it might be the third, which would be hardest to get around.
Cause One
As my comment stated, perhaps there is another model with a field that has User as a ForeignKey with on_delete = models.CASCADE. When you try to delete the User, all instances of this class that has that ForeignKey will need to be deleted as well (because of on_delete=models.CASCADE), and that's what's causing the issue. You have already stated you have no such models, so let's move on to solution 2.
Cause Two
I hope it's this one, since it might be easier to fix. I noticed you have email = models.EmailField('email', unique=True) as one of your fields for your User model, but AbstractUser should already have an email field. Try removing that field, makemigrations and migrate, and see if the issue is resolved.
Cause Three
Did you change from the default User model to the custom user you are now using in mid-project? In other words, did you, in this project, ever run makemigrations before you switched to a custom user model? That can be a big problem. However, there are two solutions for this, not so easy or desirable, but doable.
Solution A: If this is a new project with no valuable data yet, you can simpy delete your database, delete all migrations in all folders, as well as all __pycache__ folders as described here. Then re do python manage.py makemigrations and python manage.py migrate. Of course this will erase all your tables, so you wouldn't want to do this mid-project.
Solution B: There is a way to handle this mid-project without losing data. The steps are out in this django ticket 25313, or these, more readable instructions.
During my first Django app i've managed to hit this 'road-block' where i'm trying to extend User model from my .forms file where forms.py looks like this:
#forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
phone = forms.CharField(max_length=50, required=False)
class Meta:
model = User
fields = ['username', 'email', 'phone', 'password1', 'password2']
class UserLoginForm(AuthenticationForm):
class Meta:
model = User
fields = ['username', 'password']
In my .models file i'm only having a 'Profile' model which is being registered within admin.py:
#admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import *
from .forms import UserRegisterForm
admin.site.unregister(User)
class CustomUserAdmin(UserAdmin, UserRegisterForm):
fieldsets = UserAdmin.fieldsets + (
(('Personal info'), {'fields': ('phone',)}),
)
admin.site.register(User, CustomUserAdmin)
admin.site.register(Profile)
...and i'm getting this back(bare in mind i've tried also passing just my form class which resulted in allot more errors):
#error
FieldError at /admin/auth/user/1/change/
Unknown field(s) (phone) specified for User. Check fields/fieldsets/exclude attributes of class CustomUserAdmin.
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/auth/user/1/change/
Django Version: 3.0.4
So the end goal would be to have another field available in my Users/'Personal info'(that's been extended within forms.py) and also would be nice to get that field when creating a new user from within the admin page. Any help/idea would be greatly appreciated, thanks.
This question already has answers here:
Create custom user form
(2 answers)
Closed 2 years ago.
Default "Add User" Interface
In this interface I want to add first name and last name field. I know those fields are already present as optional fields in django.contrib.auth.models User model, but they don't show up in UI. Also to make those fields required, is it necessary to override existing User model?
I am new to this and have a feeling that doing so would not be a good idea.
All help is appreciated!
Subclass the UserCreationForm and use it in your custom user admin:
# forms.py
from django.contrib.auth.forms import UserCreationForm
class CustomUserCreationForm(UserCreationForm):
# make fields required if desired
# first_name = forms.CharField(required=True)
class Meta(UserCreationForm.Meta):
fields = ("username", "first_name", "last_name")
# admin.py
from django.contrib.admin.sites import site
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2',
'first_name', 'last_name'),
}),
)
site.unregister(User)
site.register(User, CustomUserAdmin)
I'm just starting out with Django and I've just revamped my project so that instead of using the base user, I use an AbstractUser model, as defined in my models.py folder
#accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# add additional fields in here
favourite_colour = models.CharField("Favourite Colour", max_length=100)
def __str__(self):
return self.email
I've also created the creation forms that work well with my signup system
#accounts/forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from django import forms
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('username', 'email', 'favourite_colour')
help_texts = {
'username': 'Make something unique',
'email': None,
}
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email', 'favourite_colour')
And now I am trying to edit the admin page so that I can change a users favourite_colour attribute. So far I have this in my admin.py file
#accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['username', 'email', 'favourite_colour']
admin.site.register(CustomUser, CustomUserAdmin)
Which shows me the favourite_colour of each user
My question is, how do I make a field to edit this CustomUser attribute once you've clicked on a user?, for example like this I'd welcome any help at all as I'm not too good at reading the docs. Please ask if you need more code adding to the question, I've never asked a Django question before
After some more looking I found a fieldsets option (link1, link2, link3) that can be used inside of my CustomUserAdmin code. In my CustomUserAdmin class I now have:
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['username', 'email', 'favourite_colour']
fieldsets = UserAdmin.fieldsets + (
('Extra Fields', {'fields': ('favourite_colour',)}),
)
I tried to extend default Django user in my project by using AbstractUser. In Django admin i couldn't see choosen user permissions.
Here is my work
from django.db import models
from django.contrib.auth.models import AbstractUser
class ExtendedUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
birth_date = models.DateField(null=True, blank=True)
After that i add my extended user in admin.py
class ExtendedUserAdmin(admin.ModelAdmin):
pass
admin.site.register(ExtendedUser, ExtendedUserAdmin)
Also add AUTH_USER_MODEL in settings.py
AUTH_USER_MODEL = '_aaron_user.ExtendedUser'
I solved this problem by importing UserAdmin and register my ExtendedUser with this model in my admin.py file.
from.models import ExtendedUser
from django.contrib.auth.admin import UserAdmin
admin.site.register(ExtendedUser, UserAdmin)
The result is choosen groups and choosen user permissions are now available.
For those who use custom User model you need to add next code in admin.py:
filter_horizontal = ('groups', 'user_permissions',)
For example:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
search_fields = ('email',)
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('email', 'is_staff', 'is_active',)
filter_horizontal = ('groups', 'user_permissions',)
class Meta:
model = CustomUser
admin.site.register(CustomUser, CustomUserAdmin)
The line filter_horizontal is taken from original django.contrib.auth.admin class UserAdmin
After that 'Choosen groups' and 'Choosen user permissions' are available.
In my case it was missing bootstrap files from static/admin|css|js