Как установить пароль для модели Custom User на странице администратора Django?
Я определил пользовательскую модель пользователя, используя класс AbstractBaseUser. Ниже приведена реализация для справки.
#models.py
class UserManager(BaseUserManager):
def create_user(self, email, firstname, lastname, contact, password):
if not email:
raise ValueError('You must provide an email address')
if not contact:
raise ValueError('You must provide a contact number')
email = self.normalize_email(email)
user = self.model(email=email, firstname=firstname, lastname=lastname, contact=contact)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, firstname, lastname, contact, password):
user = self.create_user(email, firstname, lastname, contact, password)
user.is_admin = True
user.save(using=self._db)
return user
class Users(AbstractBaseUser):
id = models.AutoField(primary_key=True)
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
contact = models.CharField(max_length=10, unique=True)
email = models.EmailField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
is_staff = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname', 'contact']
objects = UserManager()
def save(self, *args, **kwargs):
if not self.firstname or not self.lastname or not self.contact or not self.email or not self.password:
raise ValueError('All required fields must be provided')
super().save(*args, **kwargs)
def __str__(self):
return str(self.id) + '. ' + self.firstname + ' ' + self.lastname
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
class Meta:
db_table = 'users'
verbose_name_plural = 'Users'
Все работает хорошо, кроме установки пароля для нового пользователя или обновления пароля для существующего пользователя на родной странице администратора Django. При установке пароля он задает его в виде обычного текста, а не хеширует.
Вот мой код admin.py.
#admin.py
from django.contrib import admin
from .models import *
admin.site.site_header = 'ROI Administration'
admin.site.site_title = 'ROI | Admin Panel'
admin.site.index_title = 'ROI Databases'
class UsersAdmin(admin.ModelAdmin):
ordering = ['id']
readonly_fields = ['id', 'created_at', 'last_login']
fieldsets = [
(None, {'fields': ['id', 'firstname', 'lastname', 'email', 'contact', 'last_login', 'created_at', 'is_staff', 'is_admin', 'password']}),
]
admin.site.register(Users, UsersAdmin)
См. скриншот ниже.
Как мне решить эту проблему?
Вам нужно использовать специальный класс UserAdmin, как показано здесь admin.UserAdmin
. Это должно решить вашу проблему
Я провел некоторое исследование и наконец решил эту проблему. Я создал CustomUserAdmin и CustomUserChangeForm в файле admin.py.
#admin.py
from .models import *
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm, AdminPasswordChangeForm
from django.template.response import TemplateResponse
from django.core.exceptions import PermissionDenied
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = Users
fields = '__all__'
class CustomUserAdmin(BaseUserAdmin):
form = CustomUserChangeForm
add_form = UserCreationForm
ordering = ['id']
readonly_fields = ['id', 'created_at', 'last_login']
list_display = ['id', 'firstname', 'lastname', 'email', 'contact', 'is_staff', 'is_admin']
fieldsets = (
('Credentials', {'fields': ('email', 'password')}),
(('Personal info'), {'fields': ('firstname', 'lastname', 'contact')}),
('Permissions', {'fields': ('is_staff', 'is_admin')}),
('Important dates', {'fields': ('last_login', 'created_at')})
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'firstname', 'lastname', 'contact', 'password1', 'password2', 'is_staff', 'is_admin'),
}),
)
filter_horizontal = ()
list_filter = []
def change_password(self, request, user_id, form_url=''):
user = self.get_object(request, user_id)
if not self.has_change_permission(request, user):
raise PermissionDenied
if request.method == 'POST':
form = AdminPasswordChangeForm(user, request.POST)
if form.is_valid():
form.save()
return self.response_change(request, user)
else:
form = AdminPasswordChangeForm(user)
fieldsets = [(None, {'fields': list(form.base_fields)})]
admin_form = admin.helpers.AdminForm(form, fieldsets, {})
context = {
'title': f'Change password: {user.email}',
'adminForm': admin_form,
'form_url': form_url,
'form': form,
'is_popup': "_popup" in request.POST or "_popup" in request.GET,
'opts': self.model._meta,
'original': user,
'save_as': False,
'show_save': True,
**self.admin_site.each_context(request),
}
return TemplateResponse(request, 'admin/auth/user/change_password.html', context)
def get_urls(self):
from django.urls import path
urls = super().get_urls()
custom_urls = [
path(
'<user_id>/password/',
self.admin_site.admin_view(self.change_password),
name='auth_user_password_change',
),
]
return custom_urls + urls
admin.site.register(Users, CustomUserAdmin)
Это решает проблему.