Создайте учетную запись из django-admin

В моей CRM, владелец компании дает первый пароль и email новым сотрудникам. Сотрудник может изменить их позже (мне не нужно показывать их в админке, что не разрешено django по умолчанию). Но как показать поля для ввода первого пароля в админке? Например, поля - "Пароль для нового пользователя" и "Повторный пароль для нового пользователя"

models.py

class CustomUser(AbstractUser):
    [...]


    def __str__(self):
        return self.email

admin.py

from django.contrib import admin
from .models import CustomUser


admin.site.register(CustomUser)

Мне нужен этот эффект:

enter image description here

При работе с пользовательскими моделями пользователей важно убедиться, что используемые формы учитывают эту проверку пароля. У вас есть два варианта достижения этой цели:

  • Поскольку ваш класс CustomUser наследуется от AbstractUser, вы можете использовать формы, которые Django предоставляет нам для работы с экземплярами пользователей:
# forms.py

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser


class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = UserCreationForm.Meta.fields + ('email',)


class CustomUserChangeForm(UserChangeForm):

    class Meta(UserChangeForm.Meta):
        model = CustomUser
        fields = UserChangeForm.Meta.fields # Includes all fields by default, no need to specify email

Посмотрев на docs, мы видим, что наш CustomUserCreationForm будет содержать 4 поля (username, email, password1 и password2). CustomUserChangeForm будет содержать все поля модели CustomUser, но будет маскировать поле password, так что оно не будет редактироваться из самой формы. Вы можете взглянуть на исходный код UserCreationForm и UserChangeForm, чтобы увидеть, как Django обрабатывает эти формы. Если используемые поля не удовлетворяют вашим потребностям, я бы выбрал второй подход, который я объясню позже, где вы сможете настроить свои формы еще больше.

Теперь нам нужно указать, что мы хотим использовать эти формы при редактировании наших CustomUser экземпляров в админке:

# admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .models import CustomUser
from .forms import CustomUserCreationForm, CustomUserChangeForm

@admin.register(CustomUser)
class CustomUserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm
    
    fieldsets = BaseUserAdmin.fieldsets

    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = BaseUserAdmin.add_fieldsets + (
        (None, {'fields': ('email',)}),
    )

Если мы хотим настроить его лучше, мы можем выбрать второй вариант.

  • Создайте наши формы почти с нуля для обработки CustomUser экземпляров. Процесс тот же, что и раньше, но способ задания форм и их регистрации в админке другой:
# forms.py

from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError

from .models import CustomUser


class CustomUserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = CustomUser
        fields = ('email', 'is_superuser') 

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

class CustomUserChangeForm(forms.ModelForm):
    """A form for updating users. Include the fields on
    the user, but replaces the password field with admin's
    disabled password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = CustomUser
        fields = ('email', 'password', 'is_superuser')

Помните, что атрибут fields используется для управления тем, какие поля вашей модели должны быть включены в соответствующие формы, я просто добавил email и is_superuser в качестве примеров, но вы должны использовать те, которые вам нужны. Обычно формы создания отображают только необходимые поля для создания экземпляров, а формы обновления содержат все редактируемые поля вашей модели (в этом случае я бы добавил больше полей в CustomUserChangeForm, но так как у меня нет много информации о CustomUser, я просто добавил некоторые поля, которые, как я знаю, есть в модели).

Теперь нам нужно указать, что мы хотим использовать эти формы в нашей панели администратора, точно так же, как мы делали раньше, но изменив fieldsets и add_fieldsets:

# admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .models import CustomUser
from .forms import CustomUserCreationForm, CustomUserChangeForm

@admin.register(CustomUser)
class CustomUserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm
    
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Permissions', {'fields': ('is_superuser',)}),
    )

    # 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', 'is_superuser', 'password1', 'password2'),
        }),
    )

Вы можете прочитать о Настройка аутентификации в Django, если вам нужно больше контекста по этому вопросу

Вернуться на верх