I have inherited the user class to make custom authentication. I do not get password hashing this way. It just stores as plain text in MySQL database. I have created staff through admin panel and unable to login as staff. Furthermore I have also created auth API endpoints using DRF and Djoser and am unable to login with the user profiles created through Django admin panel.
Here is my code.
models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
admin.py
from .models import User
class UserAdmin(admin.ModelAdmin):
pass
admin.site.register(User, UserAdmin)
I have seen old replies in Stack Overflow suggesting changing the parent class to django.contrib.auth.admin.UserAdmin . When I try this the add user template form only has 3 fields. Username, Password and Password Confirmation.
admin.py
from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin
from .models import User
class UserAdmin(DefaultUserAdmin):
pass
admin.site.register(User, UserAdmin)
How do I solve this problem.
I wrote a custom UserAdmin as well so i guess i can help you a little bit with that
try this one:
#admin.register(User)
class UserAdmin(UserAdmin):
"""Define admin model for custom User model with no email field."""
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
list_display = ('email', 'is_staff')
search_fields = ('email',)
ordering = ('email',)
And i also think that there`s problems in your models.py bcs you dont have userManager
UserManager uses when you`re creating user so i guess problem in that
Related
Django admin site used to have a form to change the password for a user that wasn't the logged in user. You would look at the user's update page, and by the password field, there was a change password link. You would click it, and it would take you to a different page for changing the password. I used to take advantage of that page to allow changing of a user's password, without having to open the admin. In Django 4, it seems to now be missing. In fact, I can't figure out how one would change a user's password other than their own, without writing my own view.
I have 2 questions:
Is there a way in the admin site now to change a different user's password?
If this view is gone, what is now the best way for a superuser to have a view that can change passwords for a user?
Edit:
This is what I see. There is no link to change the password where there used to be.
Are you sure you have checked it right? When you select an user it appears by default in the upper part, just after some semi-blinded parameters of the password.
The problem was when I am using AbstractBaseUser, and the admin site registration I was using admin.ModelAdmin instead of UserAdmin.
from django.contrib.auth import get_user_model
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
class EmployeeAdmin(UserAdmin):
ordering = ['email', ]
list_display = ['email', ]
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Info', {'fields': ('first_name', 'last_name', 'phone',)}),
('Address', {'fields': ('address', 'city', 'state', 'zip_code')}),
('Schedule', {'fields': ('time_off',)}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
("User Details", {'fields': ('email', 'password1', 'password2')}),
("Permission", {'fields': ('is_active', 'is_staff', 'is_admin')}),
)
admin.site.register(get_user_model(), EmployeeAdmin)
I have created a CustomUser(AbstractUser) Model and in this model I want to add email id field in admin Add User Page.Currently By default first we can enter username and Password and after creating username and password we are redirected to another page where email field is available I want this email field on add User page is this possible.?
On admin django already had a BaseUserAdmin which is the default, it have 2 parts, add form and change form which both forms created from fieldsets(change form) and add_fieldsets(add form)
To add fields or remove field on add form override the BaseUserAdmin add_fieldsets:
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {'fields': ('email',)}),
)
If you are using a custom ModelAdmin which is a subclass of
django.contrib.auth.admin.UserAdmin, then you need to add your custom
fields to fieldsets (for fields to be used in editing users) and to
add_fieldsets (for fields to be used when creating a user)
second method: override add_fieldsets attribute itself:
class CustomUserAdmin(UserAdmin):
# 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', 'email', 'password1', 'password2'),
}),
)
Document: https://docs.djangoproject.com/en/3.1/topics/auth/customizing/#custom-users-and-django-contrib-admin
In admin.py of your app, create a ModelAdmin and use the fields attribute to include the email field in the view.
Example:
from django.contrib import admin
from myproject.myapp.models import CustomUser
class CustomUserAdmin(admin.ModelAdmin):
fields = ('username', 'password', 'email')
admin.site.register(CustomUser,CustomUserAdmin)
I've created a Django app having multiple types of users.
There is one Superuser who can access all the data and do the modification stuff. There are few staff users, who have limited access, mostly of view but can add new users and groups.
Below is the group permission for the staff user. He can add a new group but cannot change, view or delete existing.
But when I try to create a new group, he can assign all the possible permissions to the new group, even though he doesn't have those permissions himself. Below is the view he can see when creating a new group.
How can I only show those permissions which the staff user himself have and not to show complete options?
I am using Django 2.1
This worked for me:
Create groups with various permissions
Prevent add or delete groups
#other imports
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
list_display = ('username', 'email', 'is_staff')
list_filter = ('is_staff',)
#this displays after initial user creation for additional information
fieldsets = (
(None, {'fields': ('username', 'email', 'password')}),
('Personal info', {'fields': ('first_name',)}),
('Permissions', {'fields': ('is_staff', 'is_active', 'groups')}),
)
# 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', 'email', 'password1', 'password2')}
),
)
search_fields = ('username',)
ordering = ('username',)
#unregister the default user admin
admin.site.unregister(User)
# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)
This way, the user can not get additional permissions
When editing user model through admin interface, here's what I see:
And here's what I expect to see:
The second one allows me to modify the user permissions, the first one does not.
The User model I use on the first screenshot inherits from AbstractUser and is registered in the following way:
from django.contrib import admin
import accounts.models
admin.site.register(accounts.models.User)
In my settings:
DEBUG = True
AUTH_USER_MODEL = 'accounts.User'
What can be the problem? How do I get from the first screenshot to the second?
Had the same issue but the solution is quite simple. In your admin.py file just add 'groups', 'user_permissions' to filter_horizontal = ()
i.e
filter_horizontal = ('groups', 'user_permissions')
that is basically it.
referenced from:
https://djangobook.com/customizing-change-lists-forms/
OK, the actual problem was that I inherited not from AbstractUser but from AbstractBaseUser and forgot about PermissionsMixin (the mixin adds the apropriate fields). So I should've done something like this.
The problem in my case is that, I was inheriting only from admin.UserAdmin, I had to create a UserAdmin class that inherits from admin.ModelAdmin and add the filter_horizontal to it, I'm adding the filter every time I modify the UserAdmin, it should look like:
class UserAdmin(UserAdmin):
model = User
filter_horizontal = ('groups', 'user_permissions')
add_form = UserCreationForm
form = UserChangeForm
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('email', 'is_staff', 'is_active',)
fieldsets = (
# ('Zone label',{'fields.....'})
(None, {'fields': ('email', 'username', 'password',)}),
('Permissions', {'fields': ('is_staff', 'is_active',)}),
('Personal', {'fields': ('about',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('date_joined',)
admin.site.register(User, UserAdmin)
admin.site.unregister(User)
class UserAdmin(admin.ModelAdmin):
list_display = ['username']
filter_horizontal = ("groups", "user_permissions")
admin.site.register(User, UserAdmin)
I extend the django user model as described in the dev doc. I wan't to keep most of the original User model features so I extend the AbstractUser class. I've defined in settings.py:
AUTH_USER_MODEL = 'myapp.CustomUser'
My user class:
class CustomUser(AbstractUser):
custom_field = models.ForeignKey('OtherModel')
objects = UserManager()
Everything seems to work fine but when I try to make it managed by the admin site:
admin.site.register(CustomUser, UserAdmin)
I get this error on the admin CustomUser creation page (after validation of the password confirmation form):
AttributeError: Manager isn't available; User has been swapped for 'myapp.CustomUser'
The point is that I need this model managed by the admin site in order to have the same creation process as with the original User model (two step process with password validation).
You need only change form for adding user(overwrite clean_username and change User on get_user_model()
Full working example(If you inherited from AbstractUser)
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class MyUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
class MyUserCreationForm(UserCreationForm):
class Meta:
model = get_user_model()
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 MyUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
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(MyUser, MyUserAdmin)
I struggled with this error for hours. For me I needed to remove all references to
from django.contrib.auth.models import User
and then replace it with:
from myapp.models import MyUser as User
This is assuming your custom User model is in an app called myapp and you called the model MyUser.
I'm using as User so that I don't have to change where my existing code that makes reference to the the User object from django.contrib.auth.models.
Good luck!
Alan
#aviars
You probably should look at full example in official documentation:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example
There are some uncovered questions (permissions handling, for example), but, at least, it's working.
From Django docs:
You should also define a custom manager for your User model.
Subclass AbstractUser already handle objects = UserManager() for you (this code on github at line 327). You don't need to define it in your model again.
I'm not sure why it come with that error. But below config seem work for me with latest Dev version.
Model.py:
class CustomUser(AbstractUser):
custom_field = models.ForeignKey('OtherModel')
# remove : objects = UserManager()
I've found a solution:
I don't use UserAdmin to register the CustomUser in the admin site, I use a custom ModelAdmin.
class CustomUserAdmin(admin.ModelAdmin):
add_form = CustomUserCreationAdminForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2')}
),
)
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
return super(CustomUserAdmin, self).get_fieldsets(request, obj)
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults.update({
'form': self.add_form,
'fields': admin.util.flatten_fieldsets(self.add_fieldsets),
})
defaults.update(kwargs)
return super(CustomUserAdmin, self).get_form(request, obj, **defaults)
Because I want to have a creation form different from the update form, I override the get_form function of the Model Admin as done in the UserAdmin django code. I also have created a custom Creation form for my custom user: CustomUserCreationForm
I received a response in the django-users mailing list that may be better than mine:
Unregister the original User class from the admin site and then register the CustomUser with UserAdmin:
admin.site.unregister(User)
admin.site.register(CustomUser, UserAdmin)
Not tested yet.
EDIT: this last solution doesn't work
Regards
UserAdmin is already registered to manage User, at the end of contrib/auth/admin.py
admin.site.register(User, UserAdmin)
Given you want to register UserAdmin with CustomUser, I think you would first have to unregister the User/UserAdmin pair:
admin.site.unregister(User)
then register your new model. Given the lack of control in the order of module loading, you could create a class derived from UserAdmin and manage your user model with it. This would work everytime, if I'm thinking properly.