Как установить пароль для модели 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)

См. скриншот ниже.

Как мне это решить?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно использовать конкретный класс UserAdmin, например admin.UserAdmin. Это должно решить вашу проблему

Можете ли вы конкретно помочь в его использовании?

Mohit Aswani 01.06.2024 09:47

Если вы просто измените эту строку, все будет в порядке: class UsersAdmin(admin.ModelAdmin): -> class UsersAdmin(admin. UserAdmin):

user20223018 01.06.2024 11:28

Я пробовал с выше. Затем я получаю следующие ошибки, поскольку у меня есть настраиваемые поля в модели пользователя, как показано в проблеме. Вот что говорит ошибка. ``` ОШИБКИ: <class 'django.contrib.auth.admin.UserAdmin'>: (admin.E019) Значение 'filter_horizontal[0]' относится к "группам", которые не являются полем "app.Users" '. <класс 'django.contrib.auth.admin.UserAdmin'>: (admin.E019) Значение 'filter_horizontal[1]' относится к 'user_permissions', который не является полем 'app.Users'. ... ... ```

Mohit Aswani 01.06.2024 11:59

Затем вы можете вручную настроить этот фильтр, чтобы не включать эти поля: filter_horizontal = []

user20223018 01.06.2024 12:25

В каком файле мне изменить и какую часть кода мне изменить?

Mohit Aswani 01.06.2024 12:55

Вы можете настроить администратора пользователей, просто установите filter_horizontal = [] в этом классе.

user20223018 01.06.2024 14:50
Ответ принят как подходящий

Я провел небольшое исследование и, наконец, решил эту проблему. Я создал 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)

Это решает проблему.

Другие вопросы по теме